1/* 2 * Copyright (c) 2014 Fujitsu Ltd. 3 * Author: Xiaoguang Wang <wangxg.fnst@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 42char *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" 53static char elooppathname[sizeof(ELOPFILE) * 43] = "."; 54static int max_subdirs; 55 56static const char *device; 57static const char *fs_type; 58static int mount_flag; 59 60static void cleanup(void); 61static void setup(void); 62static void test_eloop(void); 63static void test_erofs(void); 64static void test_emlink(void); 65 66static void (*testfunc[])(void) = { test_eloop, test_erofs, test_emlink }; 67 68int TST_TOTAL = ARRAY_SIZE(testfunc); 69 70int 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 89static 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 SAFE_MOUNT(cleanup, device, MNTPOINT, fs_type, 0, NULL); 111 mount_flag = 1; 112 SAFE_TOUCH(cleanup, TEST_EROFS, 0644, NULL); 113 114 SAFE_MKDIR(cleanup, TEST_EMLINK, 0755); 115 max_subdirs = tst_fs_fill_subdirs(cleanup, "emlink_dir"); 116 /* 117 * NOTE: the ELOOP test is written based on that the consecutive 118 * symlinks limits in kernel is hardwired to 40. 119 */ 120 SAFE_MKDIR(cleanup, "test_eloop", 0644); 121 SAFE_SYMLINK(cleanup, "../test_eloop", "test_eloop/test_eloop"); 122 for (i = 0; i < 43; i++) 123 strcat(elooppathname, ELOPFILE); 124} 125 126static void check_and_print(int expected_errno) 127{ 128 if (TEST_RETURN == -1) { 129 if (TEST_ERRNO == expected_errno) { 130 tst_resm(TPASS | TTERRNO, "failed as expected"); 131 } else { 132 tst_resm(TFAIL | TTERRNO, 133 "failed unexpectedly; expected - %d : %s", 134 expected_errno, strerror(expected_errno)); 135 } 136 } else { 137 tst_resm(TFAIL, "rename succeeded unexpectedly"); 138 } 139} 140 141static void test_eloop(void) 142{ 143 TEST(rename(elooppathname, TEST_NEW_ELOOP)); 144 check_and_print(ELOOP); 145 146 if (TEST_RETURN == 0) 147 SAFE_UNLINK(cleanup, TEST_NEW_ELOOP); 148} 149 150static void test_erofs(void) 151{ 152 SAFE_MOUNT(cleanup, device, MNTPOINT, fs_type, MS_REMOUNT | MS_RDONLY, 153 NULL); 154 155 TEST(rename(TEST_EROFS, TEST_NEW_EROFS)); 156 check_and_print(EROFS); 157 158 if (TEST_RETURN == 0) 159 SAFE_UNLINK(cleanup, TEST_NEW_EROFS); 160 161 SAFE_MOUNT(cleanup, device, MNTPOINT, fs_type, MS_REMOUNT, NULL); 162} 163 164static void test_emlink(void) 165{ 166 if (max_subdirs == 0) { 167 tst_resm(TCONF, "EMLINK test is not appropriate"); 168 return; 169 } 170 171 TEST(rename(TEST_EMLINK, TEST_NEW_EMLINK)); 172 check_and_print(EMLINK); 173 174 if (TEST_RETURN == 0) 175 SAFE_RMDIR(cleanup, TEST_NEW_EMLINK); 176} 177 178static void cleanup(void) 179{ 180 if (mount_flag && tst_umount(MNTPOINT) < 0) 181 tst_resm(TWARN | TERRNO, "umount device:%s failed", device); 182 183 if (device) 184 tst_release_device(device); 185 186 tst_rmdir(); 187} 188