1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) International Business Machines Corp., 2006 4 * Copyright (c) Cyril Hrubis 2014 <chrubis@suse.cz> 5 * Copyright (c) Linux Test Project, 2003-2023 6 * Author: Yi Yang <yyangcdl@cn.ibm.com> 7 */ 8 9/*\ 10 * [Description] 11 * 12 * Check the basic functionality of the readlinkat() system call. 13 * 14 * - readlinkat() passes if dirfd is directory file descriptor 15 * and the pathname is relative. 16 * - readlinkat() passes if the pathname is abspath, then dirfd 17 * is ignored. 18 * - readlinkat() passes if dirfd is the special value AT_FDCWD 19 * and the pathname is relative. 20 * - readlinkat() passes if pathname is an empty string, in which 21 * case the call operates on the symbolic link referred to by dirfd. 22 */ 23 24#include <stdlib.h> 25#include <stdio.h> 26#include "tst_test.h" 27#include "lapi/fcntl.h" 28 29#define TEST_FILE "readlink_file" 30#define TEST_SYMLINK "readlink_symlink" 31 32static int file_fd, dir_fd, dir_fd2; 33static int fd_atcwd = AT_FDCWD; 34static const char *abspath; 35static const char *testsymlink; 36static const char *emptypath; 37 38static struct tcase { 39 int *fd; 40 const char **path; 41} tcases[] = { 42 {&dir_fd, &testsymlink}, 43 {&dir_fd, &abspath}, 44 {&file_fd, &abspath}, 45 {&fd_atcwd, &abspath}, 46 {&fd_atcwd, &testsymlink}, 47 {&dir_fd2, &emptypath}, 48}; 49 50static void verify_readlinkat(unsigned int i) 51{ 52 char buf[1024]; 53 struct tcase *tc = &tcases[i]; 54 55 memset(buf, 0, sizeof(buf)); 56 57 TST_EXP_POSITIVE(readlinkat(*tc->fd, *tc->path, buf, sizeof(buf)), 58 "readlinkat(%d, %s, %s, %ld)", 59 *tc->fd, *tc->path, buf, sizeof(buf)); 60 61 if (strcmp(buf, TEST_FILE) == 0) 62 tst_res(TPASS, "The filename in buffer is correct"); 63 else 64 tst_res(TFAIL, "Wrong filename in buffer '%s'", buf); 65} 66 67static void setup(void) 68{ 69 char *tmpdir = tst_get_tmpdir(); 70 71 abspath = tst_aprintf("%s/" TEST_SYMLINK, tmpdir); 72 free(tmpdir); 73 74 file_fd = SAFE_OPEN(TEST_FILE, O_CREAT, 0600); 75 SAFE_SYMLINK(TEST_FILE, TEST_SYMLINK); 76 dir_fd = SAFE_OPEN(".", O_DIRECTORY); 77 dir_fd2 = SAFE_OPEN(TEST_SYMLINK, O_PATH | O_NOFOLLOW); 78} 79 80static void cleanup(void) 81{ 82 if (file_fd > -1) 83 SAFE_CLOSE(file_fd); 84 85 if (dir_fd > -1) 86 SAFE_CLOSE(dir_fd); 87 88 if (dir_fd2 > -1) 89 SAFE_CLOSE(dir_fd2); 90} 91 92static struct tst_test test = { 93 .test = verify_readlinkat, 94 .needs_tmpdir = 1, 95 .setup = setup, 96 .cleanup = cleanup, 97 .bufs = (struct tst_buffers []) { 98 {&testsymlink, .str = TEST_SYMLINK}, 99 {&emptypath, .str = ""}, 100 {}, 101 }, 102 .tcnt = ARRAY_SIZE(tcases), 103}; 104