1 /* 2 * Copyright (c) 2014 Fujitsu Ltd. 3 * Author: Xiaoguang Wang <wangxg.fnst (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 13 * the GNU 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* 21 * Test Description: 22 * Verify that, 23 * 1. rename() fails with -1 return value and sets errno to ELOOP, if too 24 * many symbolic links were encountered in resolving oldpath or newpath. 25 * 2. rename() fails with -1 return value and sets errno to EROFS, 26 * if the file is on a read-only file system. 27 * 3. rename() fails with -1 return value and sets errno to EMLINK, 28 * if the file named by old is a directory and the link count of 29 * the parent directory of new would exceed {LINK_MAX}. 30 */ 31 32 #include <stdio.h> 33 #include <errno.h> 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <fcntl.h> 37 #include <sys/mount.h> 38 39 #include "test.h" 40 #include "safe_macros.h" 41 42 char *TCID = "rename11"; 43 44 #define MNTPOINT "mntpoint" 45 #define TEST_EROFS "mntpoint/test_erofs" 46 #define TEST_NEW_EROFS "mntpoint/new_test_erofs" 47 48 #define TEST_EMLINK "test_emlink" 49 #define TEST_NEW_EMLINK "emlink_dir/testdir" 50 51 #define TEST_NEW_ELOOP "new_test_eloop" 52 #define ELOPFILE "/test_eloop" 53 static char elooppathname[sizeof(ELOPFILE) * 43] = "."; 54 static int max_subdirs; 55 56 static const char *device; 57 static const char *fs_type; 58 static int mount_flag; 59 60 static void cleanup(void); 61 static void setup(void); 62 static void test_eloop(void); 63 static void test_erofs(void); 64 static void test_emlink(void); 65 66 static void (*testfunc[])(void) = { test_eloop, test_erofs, test_emlink }; 67 68 int TST_TOTAL = ARRAY_SIZE(testfunc); 69 70 int main(int ac, char **av) 71 { 72 int lc, i; 73 74 tst_parse_opts(ac, av, NULL, NULL); 75 76 setup(); 77 78 for (lc = 0; TEST_LOOPING(lc); lc++) { 79 tst_count = 0; 80 81 for (i = 0; i < TST_TOTAL; i++) 82 (*testfunc[i])(); 83 } 84 85 cleanup(); 86 tst_exit(); 87 } 88 89 static void setup(void) 90 { 91 int i; 92 93 tst_sig(NOFORK, DEF_HANDLER, cleanup); 94 95 tst_require_root(); 96 97 tst_tmpdir(); 98 99 TEST_PAUSE; 100 101 fs_type = tst_dev_fs_type(); 102 device = tst_acquire_device(cleanup); 103 104 if (!device) 105 tst_brkm(TCONF, cleanup, "Failed to obtain block device"); 106 107 tst_mkfs(cleanup, device, fs_type, NULL, NULL); 108 109 SAFE_MKDIR(cleanup, MNTPOINT, 0755); 110 if (mount(device, MNTPOINT, fs_type, 0, NULL) < 0) { 111 tst_brkm(TBROK | TERRNO, cleanup, 112 "mount device:%s failed", device); 113 } 114 mount_flag = 1; 115 SAFE_TOUCH(cleanup, TEST_EROFS, 0644, NULL); 116 117 SAFE_MKDIR(cleanup, TEST_EMLINK, 0755); 118 max_subdirs = tst_fs_fill_subdirs(cleanup, "emlink_dir"); 119 /* 120 * NOTE: the ELOOP test is written based on that the consecutive 121 * symlinks limits in kernel is hardwired to 40. 122 */ 123 SAFE_MKDIR(cleanup, "test_eloop", 0644); 124 SAFE_SYMLINK(cleanup, "../test_eloop", "test_eloop/test_eloop"); 125 for (i = 0; i < 43; i++) 126 strcat(elooppathname, ELOPFILE); 127 } 128 129 static void check_and_print(int expected_errno) 130 { 131 if (TEST_RETURN == -1) { 132 if (TEST_ERRNO == expected_errno) { 133 tst_resm(TPASS | TTERRNO, "failed as expected"); 134 } else { 135 tst_resm(TFAIL | TTERRNO, 136 "failed unexpectedly; expected - %d : %s", 137 expected_errno, strerror(expected_errno)); 138 } 139 } else { 140 tst_resm(TFAIL, "rename succeeded unexpectedly"); 141 } 142 } 143 144 static void test_eloop(void) 145 { 146 TEST(rename(elooppathname, TEST_NEW_ELOOP)); 147 check_and_print(ELOOP); 148 149 if (TEST_RETURN == 0) 150 SAFE_UNLINK(cleanup, TEST_NEW_ELOOP); 151 } 152 153 static void test_erofs(void) 154 { 155 if (mount(device, MNTPOINT, fs_type, MS_REMOUNT | MS_RDONLY, NULL) < 0) { 156 tst_brkm(TBROK | TERRNO, cleanup, 157 "mount device:%s failed", device); 158 } 159 160 TEST(rename(TEST_EROFS, TEST_NEW_EROFS)); 161 check_and_print(EROFS); 162 163 if (TEST_RETURN == 0) 164 SAFE_UNLINK(cleanup, TEST_NEW_EROFS); 165 166 if (mount(device, MNTPOINT, fs_type, MS_REMOUNT, NULL) < 0) { 167 tst_brkm(TBROK | TERRNO, cleanup, 168 "remount device:%s failed", device); 169 } 170 } 171 172 static void test_emlink(void) 173 { 174 if (max_subdirs == 0) { 175 tst_resm(TCONF, "EMLINK test is not appropriate"); 176 return; 177 } 178 179 TEST(rename(TEST_EMLINK, TEST_NEW_EMLINK)); 180 check_and_print(EMLINK); 181 182 if (TEST_RETURN == 0) 183 SAFE_RMDIR(cleanup, TEST_NEW_EMLINK); 184 } 185 186 static void cleanup(void) 187 { 188 if (mount_flag && tst_umount(MNTPOINT) < 0) 189 tst_resm(TWARN | TERRNO, "umount device:%s failed", device); 190 191 if (device) 192 tst_release_device(device); 193 194 tst_rmdir(); 195 } 196