1 /* 2 * Copyright (c) 2014 Fujitsu Ltd. 3 * Author: Zeng Linggang <zenglg.jy (at) 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 <fcntl.h> 25 #include <unistd.h> 26 #include <stdlib.h> 27 #include <errno.h> 28 #include <string.h> 29 #include <signal.h> 30 #include <pwd.h> 31 #include <sys/mount.h> 32 33 #include "test.h" 34 #include "lapi/syscalls.h" 35 #include "safe_macros.h" 36 #include "lapi/fcntl.h" 37 38 #define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \ 39 S_IXGRP|S_IROTH|S_IXOTH) 40 #define TEST_FILE "testfile" 41 #define TEST_EXIST "testexist" 42 #define TEST_ELOOP "testeloop" 43 #define TEST_EACCES "./tmp/testeeacces" 44 #define TEST_EACCES2 "./tmp/testeeacces2" 45 #define TEST_EROFS "mntpoint" 46 #define TEST_EROFS2 "mntpoint/testerofs2" 47 #define TEST_EMLINK "emlink_dir/testfile0" 48 #define TEST_EMLINK2 "emlink_dir/testfile" 49 #define BASENAME "mntpoint/basename" 50 51 static char nametoolong[PATH_MAX+2]; 52 static const char *device; 53 static int mount_flag; 54 static int max_hardlinks; 55 static const char *fs_type; 56 57 static void setup(void); 58 static void cleanup(void); 59 static void setup_eacces(void); 60 static void cleanup_eacces(void); 61 static void setup_erofs(void); 62 63 static struct test_struct { 64 const char *oldfname; 65 const char *newfname; 66 int flags; 67 int expected_errno; 68 void (*setupfunc) (void); 69 void (*cleanfunc) (void); 70 } test_cases[] = { 71 {TEST_FILE, nametoolong, 0, ENAMETOOLONG, NULL, NULL}, 72 {nametoolong, TEST_FILE, 0, ENAMETOOLONG, NULL, NULL}, 73 {TEST_EXIST, TEST_EXIST, 0, EEXIST, NULL, NULL}, 74 {TEST_ELOOP, TEST_FILE, AT_SYMLINK_FOLLOW, ELOOP, NULL, NULL}, 75 {TEST_EACCES, TEST_EACCES2, 0, EACCES, setup_eacces, cleanup_eacces}, 76 {TEST_EROFS, TEST_EROFS2, 0, EROFS, setup_erofs, NULL}, 77 {TEST_EMLINK, TEST_EMLINK2, 0, EMLINK, NULL, NULL}, 78 }; 79 80 char *TCID = "linkat02"; 81 int TST_TOTAL = ARRAY_SIZE(test_cases); 82 83 static struct passwd *ltpuser; 84 static void linkat_verify(const struct test_struct *); 85 86 int main(int ac, char **av) 87 { 88 int lc; 89 int i; 90 91 tst_parse_opts(ac, av, NULL, NULL); 92 93 setup(); 94 95 for (lc = 0; TEST_LOOPING(lc); lc++) { 96 tst_count = 0; 97 for (i = 0; i < TST_TOTAL; i++) 98 linkat_verify(&test_cases[i]); 99 } 100 101 cleanup(); 102 tst_exit(); 103 } 104 105 static void linkat_verify(const struct test_struct *desc) 106 { 107 if (desc->expected_errno == EMLINK && max_hardlinks == 0) { 108 tst_resm(TCONF, "EMLINK test is not appropriate"); 109 return; 110 } 111 112 if (desc->setupfunc != NULL) { 113 desc->setupfunc(); 114 } 115 116 TEST(ltp_syscall(__NR_linkat, AT_FDCWD, desc->oldfname, 117 AT_FDCWD, desc->newfname, desc->flags)); 118 119 if (desc->cleanfunc != NULL) 120 desc->cleanfunc(); 121 122 if (TEST_RETURN != -1) { 123 tst_resm(TFAIL, 124 "linkat(""AT_FDCWD"", %s, ""AT_FDCWD"", %s, %d)" 125 "succeeded unexpectedly", desc->oldfname, 126 desc->newfname, desc->flags); 127 return; 128 } 129 130 if (TEST_ERRNO == desc->expected_errno) { 131 tst_resm(TPASS | TTERRNO, "linkat failed as expected"); 132 } else { 133 tst_resm(TFAIL | TTERRNO, 134 "linkat failed unexpectedly; expected: " 135 "%d - %s", desc->expected_errno, 136 strerror(desc->expected_errno)); 137 } 138 } 139 140 static void setup(void) 141 { 142 if ((tst_kvercmp(2, 6, 16)) < 0) 143 tst_brkm(TCONF, NULL, "This test needs kernel 2.6.16 or newer"); 144 145 tst_require_root(); 146 147 tst_sig(NOFORK, DEF_HANDLER, cleanup); 148 149 tst_tmpdir(); 150 151 fs_type = tst_dev_fs_type(); 152 device = tst_acquire_device(cleanup); 153 154 if (!device) 155 tst_brkm(TCONF, cleanup, "Failed to acquire device"); 156 157 TEST_PAUSE; 158 159 ltpuser = SAFE_GETPWNAM(cleanup, "nobody"); 160 161 SAFE_TOUCH(cleanup, TEST_FILE, 0644, NULL); 162 163 memset(nametoolong, 'a', PATH_MAX+1); 164 165 SAFE_TOUCH(cleanup, TEST_EXIST, 0644, NULL); 166 167 SAFE_SYMLINK(cleanup, TEST_ELOOP, "test_file_eloop2"); 168 SAFE_SYMLINK(cleanup, "test_file_eloop2", TEST_ELOOP); 169 170 SAFE_MKDIR(cleanup, "./tmp", DIR_MODE); 171 SAFE_TOUCH(cleanup, TEST_EACCES, 0666, NULL); 172 173 tst_mkfs(cleanup, device, fs_type, NULL, NULL); 174 SAFE_MKDIR(cleanup, "mntpoint", DIR_MODE); 175 176 SAFE_MOUNT(cleanup, device, "mntpoint", fs_type, 0, NULL); 177 mount_flag = 1; 178 179 max_hardlinks = tst_fs_fill_hardlinks(cleanup, "emlink_dir"); 180 } 181 182 static void setup_eacces(void) 183 { 184 SAFE_SETEUID(cleanup, ltpuser->pw_uid); 185 } 186 187 static void cleanup_eacces(void) 188 { 189 SAFE_SETEUID(cleanup, 0); 190 } 191 192 static void setup_erofs(void) 193 { 194 SAFE_MOUNT(cleanup, device, "mntpoint", fs_type, 195 MS_REMOUNT | MS_RDONLY, NULL); 196 mount_flag = 1; 197 } 198 199 static void cleanup(void) 200 { 201 if (mount_flag && tst_umount("mntpoint") < 0) 202 tst_resm(TWARN | TERRNO, "umount device:%s failed", device); 203 204 if (device) 205 tst_release_device(device); 206 207 tst_rmdir(); 208 } 209