1/****************************************************************************** 2 * 3 * Copyright (c) International Business Machines Corp., 2006 4 * Author: Yi Yang <yyangcdl@cn.ibm.com> 5 * Copyright (c) Cyril Hrubis 2014 <chrubis@suse.cz> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 15 * the GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 * 21 * This test case will verify basic function of readlinkat 22 * added by kernel 2.6.16 or up. 23 * 24 *****************************************************************************/ 25 26#define _GNU_SOURCE 27 28#include <sys/types.h> 29#include <sys/stat.h> 30#include <sys/time.h> 31#include <fcntl.h> 32#include <error.h> 33#include <stdlib.h> 34#include <errno.h> 35#include <string.h> 36#include <signal.h> 37#include "test.h" 38#include "safe_macros.h" 39#include "lapi/readlinkat.h" 40 41static void setup(void); 42static void cleanup(void); 43 44char *TCID = "readlinkat01"; 45 46static int dir_fd, fd; 47static int fd_invalid = 100; 48static int fd_atcwd = AT_FDCWD; 49 50#define TEST_SYMLINK "readlink_symlink" 51#define TEST_FILE "readlink_file" 52 53static char abspath[1024]; 54 55static struct test_case { 56 int *dir_fd; 57 const char *path; 58 const char *exp_buf; 59 int exp_ret; 60 int exp_errno; 61} test_cases[] = { 62 {&dir_fd, TEST_SYMLINK, TEST_FILE, sizeof(TEST_FILE)-1, 0}, 63 {&dir_fd, abspath, TEST_FILE, sizeof(TEST_FILE)-1, 0}, 64 {&fd, TEST_SYMLINK, NULL, -1, ENOTDIR}, 65 {&fd_invalid, TEST_SYMLINK, NULL, -1, EBADF}, 66 {&fd_atcwd, TEST_SYMLINK, TEST_FILE, sizeof(TEST_FILE)-1, 0}, 67}; 68 69int TST_TOTAL = ARRAY_SIZE(test_cases); 70 71static void verify_readlinkat(struct test_case *test) 72{ 73 char buf[1024]; 74 75 memset(buf, 0, sizeof(buf)); 76 77 TEST(readlinkat(*test->dir_fd, test->path, buf, sizeof(buf))); 78 79 if (TEST_RETURN != test->exp_ret) { 80 tst_resm(TFAIL | TTERRNO, 81 "readlinkat() returned %ld, expected %d", 82 TEST_RETURN, test->exp_ret); 83 return; 84 } 85 86 if (TEST_ERRNO != test->exp_errno) { 87 tst_resm(TFAIL | TTERRNO, 88 "readlinkat() returned %ld, expected %d", 89 TEST_RETURN, test->exp_ret); 90 return; 91 } 92 93 if (test->exp_ret > 0 && strcmp(test->exp_buf, buf)) { 94 tst_resm(TFAIL, "Unexpected buffer have '%s', expected '%s'", 95 buf, test->exp_buf); 96 return; 97 } 98 99 tst_resm(TPASS | TTERRNO, "readlinkat() returned %ld", TEST_RETURN); 100} 101 102int main(int ac, char **av) 103{ 104 int lc; 105 int i; 106 107 tst_parse_opts(ac, av, NULL, NULL); 108 109 setup(); 110 111 for (lc = 0; TEST_LOOPING(lc); lc++) { 112 for (i = 0; i < TST_TOTAL; i++) 113 verify_readlinkat(&test_cases[i]); 114 } 115 116 cleanup(); 117 tst_exit(); 118} 119 120static void setup(void) 121{ 122 tst_tmpdir(); 123 char *tmpdir = tst_get_tmpdir(); 124 125 snprintf(abspath, sizeof(abspath), "%s/" TEST_SYMLINK, tmpdir); 126 free(tmpdir); 127 128 fd = SAFE_OPEN(cleanup, TEST_FILE, O_CREAT, 0600); 129 SAFE_SYMLINK(cleanup, TEST_FILE, TEST_SYMLINK); 130 dir_fd = SAFE_OPEN(cleanup, ".", O_DIRECTORY); 131 132 TEST_PAUSE; 133} 134 135static void cleanup(void) 136{ 137 if (fd > 0 && close(fd)) 138 tst_resm(TWARN | TERRNO, "Failed to close fd"); 139 140 if (dir_fd > 0 && close(dir_fd)) 141 tst_resm(TWARN | TERRNO, "Failed to close dir_fd"); 142 143 tst_rmdir(); 144} 145