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 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 the 13 * GNU Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * 19 */ 20 /* 21 * Test Description: 22 * Verify that, 23 * 1. link() fails with -1 return value and sets errno to EPERM 24 * if oldpath is a directory. 25 * 2. link() fails with -1 return value and sets errno to EXDEV 26 * if oldpath and newpath are not on the same mounted file system( Linux 27 * permits a file system to be mounted at multiple points, but link() 28 * does not work across different mount points, even if the same 29 * file system is mounted on both. ). 30 * 3. link() fails with -1 return value and sets errno to EROFS 31 * if the file is on a read-only file system. 32 * 4. link() fails with -1 return value and sets errno to ELOOP 33 * if too many symbolic links were encountered in resolving path. 34 */ 35 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <unistd.h> 39 #include <fcntl.h> 40 #include <errno.h> 41 #include <string.h> 42 #include <signal.h> 43 #include <sys/types.h> 44 #include <sys/stat.h> 45 #include <pwd.h> 46 #include <sys/mount.h> 47 48 #include "test.h" 49 #include "safe_macros.h" 50 51 #define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \ 52 S_IXGRP|S_IROTH|S_IXOTH) 53 #define MNT_POINT "mntpoint" 54 #define TEST_FILE "testfile" 55 #define TEST_FILE1 "testfile1" 56 #define TEST_FILE2 "mntpoint/testfile3" 57 #define TEST_FILE3 "mntpoint/testfile4" 58 59 static char test_file4[PATH_MAX] = "."; 60 static void setup(void); 61 static void cleanup(void); 62 63 static const char *device; 64 static int mount_flag; 65 66 static struct test_case_t { 67 char *oldpath; 68 char *newpath; 69 int exp_errno; 70 } test_cases[] = { 71 {TEST_FILE1, TEST_FILE, EPERM}, 72 {TEST_FILE2, TEST_FILE, EXDEV}, 73 {TEST_FILE2, TEST_FILE3, EROFS}, 74 {test_file4, TEST_FILE, ELOOP}, 75 }; 76 77 static void link_verify(const struct test_case_t *); 78 79 char *TCID = "link08"; 80 int TST_TOTAL = ARRAY_SIZE(test_cases); 81 82 int main(int ac, char **av) 83 { 84 int i, lc; 85 86 tst_parse_opts(ac, av, NULL, NULL); 87 88 setup(); 89 90 for (lc = 0; TEST_LOOPING(lc); lc++) { 91 tst_count = 0; 92 for (i = 0; i < TST_TOTAL; i++) 93 link_verify(&test_cases[i]); 94 } 95 96 cleanup(); 97 tst_exit(); 98 99 } 100 101 static void link_verify(const struct test_case_t *tc) 102 { 103 TEST(link(tc->oldpath, tc->newpath)); 104 105 if (TEST_RETURN != -1) { 106 tst_resm(TFAIL, "link succeeded unexpectedly"); 107 return; 108 } 109 110 if (TEST_ERRNO == tc->exp_errno) { 111 tst_resm(TPASS | TTERRNO, "link failed as expected"); 112 } else { 113 tst_resm(TFAIL | TTERRNO, 114 "link failed unexpectedly; expected: %d - %s", 115 tc->exp_errno, strerror(tc->exp_errno)); 116 } 117 } 118 119 120 static void setup(void) 121 { 122 int i; 123 const char *fs_type; 124 125 tst_require_root(); 126 127 tst_sig(NOFORK, DEF_HANDLER, cleanup); 128 129 TEST_PAUSE; 130 131 tst_tmpdir(); 132 133 fs_type = tst_dev_fs_type(); 134 device = tst_acquire_device(cleanup); 135 136 if (!device) 137 tst_brkm(TCONF, cleanup, "Failed to acquire device"); 138 139 SAFE_MKDIR(cleanup, TEST_FILE1, DIR_MODE); 140 141 SAFE_MKDIR(cleanup, "test_eloop", DIR_MODE); 142 SAFE_SYMLINK(cleanup, "../test_eloop", "test_eloop/test_eloop"); 143 for (i = 0; i < 43; i++) 144 strcat(test_file4, "/test_eloop"); 145 146 tst_mkfs(cleanup, device, fs_type, NULL, NULL); 147 SAFE_MKDIR(cleanup, MNT_POINT, DIR_MODE); 148 if (mount(device, MNT_POINT, fs_type, 0, NULL) < 0) { 149 tst_brkm(TBROK | TERRNO, cleanup, 150 "mount device:%s failed", device); 151 } 152 mount_flag = 1; 153 154 SAFE_TOUCH(cleanup, TEST_FILE2, 0644, NULL); 155 if (mount(device, MNT_POINT, fs_type, 156 MS_REMOUNT | MS_RDONLY, NULL) < 0) { 157 tst_brkm(TBROK | TERRNO, cleanup, 158 "mount device:%s failed", device); 159 } 160 } 161 162 static void cleanup(void) 163 { 164 if (mount_flag && tst_umount(MNT_POINT) < 0) 165 tst_resm(TWARN | TERRNO, "umount device:%s failed", device); 166 167 if (device) 168 tst_release_device(device); 169 170 tst_rmdir(); 171 } 172