1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 4f08c3bdfSopenharmony_ci * Ported to LTP: Wayne Boyer 5f08c3bdfSopenharmony_ci */ 6f08c3bdfSopenharmony_ci 7f08c3bdfSopenharmony_ci/* 8f08c3bdfSopenharmony_ci * Test Description : 9f08c3bdfSopenharmony_ci * 1) readlink(2) returns -1 and sets errno to EACCES if search/write 10f08c3bdfSopenharmony_ci * permission is denied in the directory where the symbolic link 11f08c3bdfSopenharmony_ci * resides. 12f08c3bdfSopenharmony_ci * 2) readlink(2) returns -1 and sets errno to EINVAL if the buffer size 13f08c3bdfSopenharmony_ci * is not positive. 14f08c3bdfSopenharmony_ci * 3) readlink(2) returns -1 and sets errno to EINVAL if the specified 15f08c3bdfSopenharmony_ci * file is not a symbolic link file. 16f08c3bdfSopenharmony_ci * 4) readlink(2) returns -1 and sets errno to ENAMETOOLONG if the 17f08c3bdfSopenharmony_ci * pathname component of symbolic link is too long (ie, > PATH_MAX). 18f08c3bdfSopenharmony_ci * 5) readlink(2) returns -1 and sets errno to ENOENT if the component of 19f08c3bdfSopenharmony_ci * symbolic link points to an empty string. 20f08c3bdfSopenharmony_ci * 6) readlink(2) returns -1 and sets errno to ENOTDIR if a component of 21f08c3bdfSopenharmony_ci * the path prefix is not a directory. 22f08c3bdfSopenharmony_ci * 7) readlink(2) returns -1 and sets errno to ELOOP if too many symbolic 23f08c3bdfSopenharmony_ci * links were encountered in translating the pathname. 24f08c3bdfSopenharmony_ci * 8) readlink(2) returns -1 and sets errno to EFAULT if buf outside the 25f08c3bdfSopenharmony_ci * process allocated address space. 26f08c3bdfSopenharmony_ci */ 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_ci#include <pwd.h> 29f08c3bdfSopenharmony_ci#include <errno.h> 30f08c3bdfSopenharmony_ci#include <string.h> 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_ci#include "tst_test.h" 33f08c3bdfSopenharmony_ci 34f08c3bdfSopenharmony_ci#define DIR_TEMP "test_dir_1" 35f08c3bdfSopenharmony_ci#define TEST_FILE1 "test_dir_1/test_file_1" 36f08c3bdfSopenharmony_ci#define SYM_FILE1 "test_dir_1/slink_file_1" 37f08c3bdfSopenharmony_ci#define TEST_FILE2 "test_file_2" 38f08c3bdfSopenharmony_ci#define SYM_FILE2 "slink_file_2" 39f08c3bdfSopenharmony_ci#define TEST_FILE3 "test_file_3" 40f08c3bdfSopenharmony_ci#define SYM_FILE3 "test_file_3/slink_file_3" 41f08c3bdfSopenharmony_ci#define ELOOPFILE "/test_eloop" 42f08c3bdfSopenharmony_ci#define TESTFILE "test_file" 43f08c3bdfSopenharmony_ci#define SYMFILE "slink_file" 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_cistatic char longpathname[PATH_MAX + 2]; 46f08c3bdfSopenharmony_cistatic char elooppathname[sizeof(ELOOPFILE) * 43] = "."; 47f08c3bdfSopenharmony_cistatic char buffer[256]; 48f08c3bdfSopenharmony_ci 49f08c3bdfSopenharmony_cistatic struct tcase { 50f08c3bdfSopenharmony_ci char *link; 51f08c3bdfSopenharmony_ci char *buf; 52f08c3bdfSopenharmony_ci size_t buf_size; 53f08c3bdfSopenharmony_ci int exp_errno; 54f08c3bdfSopenharmony_ci} tcases[] = { 55f08c3bdfSopenharmony_ci {SYM_FILE1, buffer, sizeof(buffer), EACCES}, 56f08c3bdfSopenharmony_ci {SYM_FILE2, buffer, 0, EINVAL}, 57f08c3bdfSopenharmony_ci {TEST_FILE2, buffer, sizeof(buffer), EINVAL}, 58f08c3bdfSopenharmony_ci {longpathname, buffer, sizeof(buffer), ENAMETOOLONG}, 59f08c3bdfSopenharmony_ci {"", buffer, sizeof(buffer), ENOENT}, 60f08c3bdfSopenharmony_ci {SYM_FILE3, buffer, sizeof(buffer), ENOTDIR}, 61f08c3bdfSopenharmony_ci {elooppathname, buffer, sizeof(buffer), ELOOP}, 62f08c3bdfSopenharmony_ci {SYMFILE, (char *)-1, sizeof(buffer), EFAULT}, 63f08c3bdfSopenharmony_ci}; 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_cistatic void verify_readlink(unsigned int n) 66f08c3bdfSopenharmony_ci{ 67f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[n]; 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_ci TEST(readlink(tc->link, tc->buf, tc->buf_size)); 70f08c3bdfSopenharmony_ci if (TST_RET != -1) { 71f08c3bdfSopenharmony_ci tst_res(TFAIL, "readlink() sueeeeded unexpectedly"); 72f08c3bdfSopenharmony_ci return; 73f08c3bdfSopenharmony_ci } 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci if (TST_ERR != tc->exp_errno) { 76f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 77f08c3bdfSopenharmony_ci "readlink() failed unexpectedly; expected: %d - %s, got", 78f08c3bdfSopenharmony_ci tc->exp_errno, tst_strerrno(tc->exp_errno)); 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci if (tc->exp_errno == ENOENT && TST_ERR == EINVAL) { 81f08c3bdfSopenharmony_ci tst_res(TWARN | TTERRNO, 82f08c3bdfSopenharmony_ci "It may be a Kernel Bug, see the patch:" 83f08c3bdfSopenharmony_ci "http://git.kernel.org/linus/1fa1e7f6"); 84f08c3bdfSopenharmony_ci } 85f08c3bdfSopenharmony_ci } else { 86f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "readlink() failed as expected"); 87f08c3bdfSopenharmony_ci } 88f08c3bdfSopenharmony_ci} 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_cistatic void setup(void) 91f08c3bdfSopenharmony_ci{ 92f08c3bdfSopenharmony_ci int i; 93f08c3bdfSopenharmony_ci struct passwd *pwent; 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ci pwent = SAFE_GETPWNAM("nobody"); 96f08c3bdfSopenharmony_ci SAFE_SETEUID(pwent->pw_uid); 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci SAFE_MKDIR(DIR_TEMP, 0777); 99f08c3bdfSopenharmony_ci SAFE_TOUCH(TEST_FILE1, 0666, NULL); 100f08c3bdfSopenharmony_ci SAFE_SYMLINK(TEST_FILE1, SYM_FILE1); 101f08c3bdfSopenharmony_ci SAFE_CHMOD(DIR_TEMP, 0444); 102f08c3bdfSopenharmony_ci 103f08c3bdfSopenharmony_ci SAFE_TOUCH(TEST_FILE2, 0666, NULL); 104f08c3bdfSopenharmony_ci SAFE_SYMLINK(TEST_FILE2, SYM_FILE2); 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_ci memset(longpathname, 'a', PATH_MAX + 1); 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci SAFE_TOUCH(TEST_FILE3, 0666, NULL); 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_ci SAFE_MKDIR("test_eloop", 0777); 111f08c3bdfSopenharmony_ci SAFE_SYMLINK("../test_eloop", "test_eloop/test_eloop"); 112f08c3bdfSopenharmony_ci 113f08c3bdfSopenharmony_ci for (i = 0; i < 43; i++) 114f08c3bdfSopenharmony_ci strcat(elooppathname, ELOOPFILE); 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci SAFE_TOUCH(TESTFILE, 0666, NULL); 117f08c3bdfSopenharmony_ci SAFE_SYMLINK(TESTFILE, SYMFILE); 118f08c3bdfSopenharmony_ci} 119f08c3bdfSopenharmony_ci 120f08c3bdfSopenharmony_cistatic struct tst_test test = { 121f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 122f08c3bdfSopenharmony_ci .test = verify_readlink, 123f08c3bdfSopenharmony_ci .setup = setup, 124f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 125f08c3bdfSopenharmony_ci .needs_root = 1, 126f08c3bdfSopenharmony_ci}; 127