1/* 2 * Copyright (c) 2014 Fujitsu Ltd. 3 * Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program. 15 */ 16/* 17 * Test that linkat() fails and sets the proper errno values. 18 */ 19 20#define _GNU_SOURCE 21 22#include <sys/types.h> 23#include <sys/stat.h> 24#include <unistd.h> 25#include <stdlib.h> 26#include <errno.h> 27#include <string.h> 28#include <signal.h> 29#include <pwd.h> 30#include <sys/mount.h> 31 32#include "test.h" 33#include "lapi/syscalls.h" 34#include "safe_macros.h" 35#include "lapi/fcntl.h" 36 37#define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \ 38 S_IXGRP|S_IROTH|S_IXOTH) 39#define TEST_FILE "testfile" 40#define TEST_EXIST "testexist" 41#define TEST_ELOOP "testeloop" 42#define TEST_EACCES "./tmp/testeeacces" 43#define TEST_EACCES2 "./tmp/testeeacces2" 44#define TEST_EROFS "mntpoint" 45#define TEST_EROFS2 "mntpoint/testerofs2" 46#define TEST_EMLINK "emlink_dir/testfile0" 47#define TEST_EMLINK2 "emlink_dir/testfile" 48#define BASENAME "mntpoint/basename" 49 50static char nametoolong[PATH_MAX+2]; 51static const char *device; 52static int mount_flag; 53static int max_hardlinks; 54static const char *fs_type; 55 56static void setup(void); 57static void cleanup(void); 58static void setup_eacces(void); 59static void cleanup_eacces(void); 60static void setup_erofs(void); 61 62static struct test_struct { 63 const char *oldfname; 64 const char *newfname; 65 int flags; 66 int expected_errno; 67 void (*setupfunc) (void); 68 void (*cleanfunc) (void); 69} test_cases[] = { 70 {TEST_FILE, nametoolong, 0, ENAMETOOLONG, NULL, NULL}, 71 {nametoolong, TEST_FILE, 0, ENAMETOOLONG, NULL, NULL}, 72 {TEST_EXIST, TEST_EXIST, 0, EEXIST, NULL, NULL}, 73 {TEST_ELOOP, TEST_FILE, AT_SYMLINK_FOLLOW, ELOOP, NULL, NULL}, 74 {TEST_EACCES, TEST_EACCES2, 0, EACCES, setup_eacces, cleanup_eacces}, 75 {TEST_EROFS, TEST_EROFS2, 0, EROFS, setup_erofs, NULL}, 76 {TEST_EMLINK, TEST_EMLINK2, 0, EMLINK, NULL, NULL}, 77}; 78 79char *TCID = "linkat02"; 80int TST_TOTAL = ARRAY_SIZE(test_cases); 81 82static struct passwd *ltpuser; 83static void linkat_verify(const struct test_struct *); 84 85int main(int ac, char **av) 86{ 87 int lc; 88 int i; 89 90 tst_parse_opts(ac, av, NULL, NULL); 91 92 setup(); 93 94 for (lc = 0; TEST_LOOPING(lc); lc++) { 95 tst_count = 0; 96 for (i = 0; i < TST_TOTAL; i++) 97 linkat_verify(&test_cases[i]); 98 } 99 100 cleanup(); 101 tst_exit(); 102} 103 104static void linkat_verify(const struct test_struct *desc) 105{ 106 if (desc->expected_errno == EMLINK && max_hardlinks == 0) { 107 tst_resm(TCONF, "EMLINK test is not appropriate"); 108 return; 109 } 110 111 if (desc->setupfunc != NULL) { 112 desc->setupfunc(); 113 } 114 115 TEST(tst_syscall(__NR_linkat, AT_FDCWD, desc->oldfname, 116 AT_FDCWD, desc->newfname, desc->flags)); 117 118 if (desc->cleanfunc != NULL) 119 desc->cleanfunc(); 120 121 if (TEST_RETURN != -1) { 122 tst_resm(TFAIL, 123 "linkat(""AT_FDCWD"", %s, ""AT_FDCWD"", %s, %d) " 124 "succeeded unexpectedly", desc->oldfname, 125 desc->newfname, desc->flags); 126 return; 127 } 128 129 if (TEST_ERRNO == desc->expected_errno) { 130 tst_resm(TPASS | TTERRNO, "linkat failed as expected"); 131 } else { 132 tst_resm(TFAIL | TTERRNO, 133 "linkat failed unexpectedly; expected: " 134 "%d - %s", desc->expected_errno, 135 strerror(desc->expected_errno)); 136 } 137} 138 139static void setup(void) 140{ 141 tst_require_root(); 142 143 tst_sig(NOFORK, DEF_HANDLER, cleanup); 144 145 tst_tmpdir(); 146 147 fs_type = tst_dev_fs_type(); 148 device = tst_acquire_device(cleanup); 149 150 if (!device) 151 tst_brkm(TCONF, cleanup, "Failed to acquire device"); 152 153 TEST_PAUSE; 154 155 ltpuser = SAFE_GETPWNAM(cleanup, "nobody"); 156 157 SAFE_TOUCH(cleanup, TEST_FILE, 0644, NULL); 158 159 memset(nametoolong, 'a', PATH_MAX+1); 160 161 SAFE_TOUCH(cleanup, TEST_EXIST, 0644, NULL); 162 163 SAFE_SYMLINK(cleanup, TEST_ELOOP, "test_file_eloop2"); 164 SAFE_SYMLINK(cleanup, "test_file_eloop2", TEST_ELOOP); 165 166 SAFE_MKDIR(cleanup, "./tmp", DIR_MODE); 167 SAFE_TOUCH(cleanup, TEST_EACCES, 0666, NULL); 168 169 tst_mkfs(cleanup, device, fs_type, NULL, NULL); 170 SAFE_MKDIR(cleanup, "mntpoint", DIR_MODE); 171 172 SAFE_MOUNT(cleanup, device, "mntpoint", fs_type, 0, NULL); 173 mount_flag = 1; 174 175 max_hardlinks = tst_fs_fill_hardlinks(cleanup, "emlink_dir"); 176} 177 178static void setup_eacces(void) 179{ 180 SAFE_SETEUID(cleanup, ltpuser->pw_uid); 181} 182 183static void cleanup_eacces(void) 184{ 185 SAFE_SETEUID(cleanup, 0); 186} 187 188static void setup_erofs(void) 189{ 190 SAFE_MOUNT(cleanup, device, "mntpoint", fs_type, 191 MS_REMOUNT | MS_RDONLY, NULL); 192 mount_flag = 1; 193} 194 195static void cleanup(void) 196{ 197 if (mount_flag && tst_umount("mntpoint") < 0) 198 tst_resm(TWARN | TERRNO, "umount device:%s failed", device); 199 200 if (device) 201 tst_release_device(device); 202 203 tst_rmdir(); 204} 205