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