1/* 2 * Copyright (c) 2015 Cedric Hnyda <chnyda@suse.com> 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of 7 * the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it would be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 /* Description: 20 * Verify that: 21 * 1) renameat2(2) returns -1 and sets errno to EEXIST because newpath 22 * already exists and the flag RENAME_NOREPLACE is used. 23 * 2) renameat2(2) returns 0. 24 * 3) renameat2(2) returns -1 and sets errno to ENOENT because the flag 25 * RENAME_EXCHANGE is used and newpath does not exist. 26 * 4) renameat2(2) returns 0 because the flag RENAME_NOREPLACE is used, 27 * both olddirfd and newdirfd are valid and oldpath exists and 28 * newpath does not exist. 29 * 5) renameat2(2) returns -1 and sets errno to EINVAL because 30 * RENAME_NOREPLACE and RENAME_EXCHANGE are used together 31 * 6) renameat2(2) returns -1 and sets errno to EINVAL because 32 * RENAME_WHITEOUT and RENAME_EXCHANGE are used together 33 */ 34 35#define _GNU_SOURCE 36 37#include "test.h" 38#include "safe_macros.h" 39#include "lapi/fcntl.h" 40#include "renameat2.h" 41 42#define TEST_DIR "test_dir/" 43#define TEST_DIR2 "test_dir2/" 44 45#define TEST_FILE "test_file" 46#define TEST_FILE2 "test_file2" 47#define TEST_FILE3 "test_file3" 48#define NON_EXIST "non_exist" 49 50char *TCID = "renameat201"; 51 52static int olddirfd; 53static int newdirfd; 54static long fs_type; 55 56static struct test_case { 57 int *olddirfd; 58 const char *oldpath; 59 int *newdirfd; 60 const char *newpath; 61 int flags; 62 int exp_errno; 63} test_cases[] = { 64 {&olddirfd, TEST_FILE, &newdirfd, TEST_FILE2, RENAME_NOREPLACE, EEXIST}, 65 {&olddirfd, TEST_FILE, &newdirfd, TEST_FILE2, RENAME_EXCHANGE, 0}, 66 {&olddirfd, TEST_FILE, &newdirfd, NON_EXIST, RENAME_EXCHANGE, ENOENT}, 67 {&olddirfd, TEST_FILE, &newdirfd, TEST_FILE3, RENAME_NOREPLACE, 0}, 68 {&olddirfd, TEST_FILE, &newdirfd, TEST_FILE2, RENAME_NOREPLACE 69 | RENAME_EXCHANGE, EINVAL}, 70 {&olddirfd, TEST_FILE, &newdirfd, TEST_FILE2, RENAME_WHITEOUT 71 | RENAME_EXCHANGE, EINVAL} 72}; 73 74int TST_TOTAL = ARRAY_SIZE(test_cases); 75 76static void setup(void); 77static void cleanup(void); 78static void renameat2_verify(const struct test_case *test); 79 80 81int main(int ac, char **av) 82{ 83 int i; 84 int lc; 85 86 tst_parse_opts(ac, av, NULL, NULL); 87 88 setup(); 89 90 for (lc = 0; lc < TEST_LOOPING(lc); lc++) { 91 tst_count = 0; 92 93 for (i = 0; i < TST_TOTAL; i++) 94 renameat2_verify(&test_cases[i]); 95 } 96 97 cleanup(); 98 tst_exit(); 99} 100 101static void setup(void) 102{ 103 if ((tst_kvercmp(3, 15, 0)) < 0) { 104 tst_brkm(TCONF, NULL, 105 "This test can only run on kernels that are 3.15. and higher"); 106 } 107 108 tst_tmpdir(); 109 110 fs_type = tst_fs_type(cleanup, "."); 111 112 SAFE_MKDIR(cleanup, TEST_DIR, 0700); 113 SAFE_MKDIR(cleanup, TEST_DIR2, 0700); 114 115 SAFE_TOUCH(cleanup, TEST_DIR TEST_FILE, 0600, NULL); 116 SAFE_TOUCH(cleanup, TEST_DIR2 TEST_FILE2, 0600, NULL); 117 SAFE_TOUCH(cleanup, TEST_DIR TEST_FILE3, 0600, NULL); 118 119 olddirfd = SAFE_OPEN(cleanup, TEST_DIR, O_DIRECTORY); 120 newdirfd = SAFE_OPEN(cleanup, TEST_DIR2, O_DIRECTORY); 121} 122 123static void cleanup(void) 124{ 125 if (olddirfd > 0 && close(olddirfd) < 0) 126 tst_resm(TWARN | TERRNO, "close olddirfd failed"); 127 128 if (newdirfd > 0 && close(newdirfd) < 0) 129 tst_resm(TWARN | TERRNO, "close newdirfd failed"); 130 131 tst_rmdir(); 132 133} 134 135static void renameat2_verify(const struct test_case *test) 136{ 137 TEST(renameat2(*(test->olddirfd), test->oldpath, 138 *(test->newdirfd), test->newpath, test->flags)); 139 140 if ((test->flags & RENAME_EXCHANGE) && EINVAL == TEST_ERRNO 141 && fs_type == TST_BTRFS_MAGIC) { 142 tst_resm(TCONF, 143 "RENAME_EXCHANGE flag is not implemeted on %s", 144 tst_fs_type_name(fs_type)); 145 return; 146 } 147 148 if (test->exp_errno && TEST_RETURN != -1) { 149 tst_resm(TFAIL, "renameat2() succeeded unexpectedly"); 150 return; 151 } 152 153 if (test->exp_errno == 0 && TEST_RETURN != 0) { 154 tst_resm(TFAIL | TTERRNO, "renameat2() failed unexpectedly"); 155 return; 156 } 157 158 if (test->exp_errno == TEST_ERRNO) { 159 tst_resm(TPASS | TTERRNO, 160 "renameat2() returned the expected value"); 161 return; 162 } 163 164 tst_resm(TFAIL | TTERRNO, 165 "renameat2() got unexpected return value: expected: %d - %s", 166 test->exp_errno, tst_strerrno(test->exp_errno)); 167 168} 169