1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 07/2001 Ported by Wayne Boyer 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 Foundation, 17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 /* 20 * Description: 21 * 1) create a directory tstdir1, create a file under it. 22 * call rmdir(tstdir1), verify the return value is -1 23 * and the errno is ENOTEMPTY. 24 * 2) create a directory with long path, call rmdir(tstdir1), 25 * verify the return value is -1 and the errno is ENAMETOOLONG. 26 * 3) pass a pathname containing non-exist directory component 27 * to rmdir(), verify the return value is -1 and the errno 28 * is ENOENT. 29 * 4) pass a pathname containing a file component to rmdir(), 30 * verify the return value is -1 and the errno is ENOTDIR. 31 * 5) attempt to pass an invalid pathname with an address 32 * pointing outside the address space of the process, as the 33 * argument to rmdir(), verify the return value is -1 and 34 * the errno is EFAULT. 35 * 6) attempt to pass an invalid pathname with NULL, as the 36 * argument to rmdir(), verify the return value is -1 and 37 * the errno is EFAULT. 38 * 7) pass a pathname with too many symbolic links to rmdir(), 39 * verify the return value is -1 and the errno is ELOOP. 40 * 8) pass a pathname which refers to a directory on a read-only 41 * file system to rmdir(), verify the return value is -1 and 42 * the errno is EROFS. 43 * 9) pass a pathname which is currently used as a mount point 44 * to rmdir(), verify the return value is -1 and the errno is 45 * EBUSY. 46 */ 47 48 #include <errno.h> 49 #include <sys/stat.h> 50 #include <sys/types.h> 51 #include <sys/mman.h> 52 #include <fcntl.h> 53 #include <unistd.h> 54 #include <pwd.h> 55 #include <sys/mount.h> 56 57 #include "test.h" 58 #include "safe_macros.h" 59 60 #define DIR_MODE (S_IRWXU | S_IRWXG | S_IRWXO) 61 #define FILE_MODE (S_IRWXU | S_IRWXG | S_IRWXO) 62 63 #define TESTDIR "testdir" 64 #define TESTDIR2 "nosuchdir/testdir2" 65 #define TESTDIR3 "testfile2/testdir3" 66 #define TESTDIR4 "/loopdir" 67 #define MNTPOINT "mntpoint" 68 #define TESTDIR5 "mntpoint/testdir5" 69 #define TESTFILE "testdir/testfile" 70 #define TESTFILE2 "testfile2" 71 72 static char longpathname[PATH_MAX + 2]; 73 static char looppathname[sizeof(TESTDIR4) * 43] = "."; 74 75 static const char *device; 76 static int mount_flag; 77 78 static struct test_case_t { 79 char *dir; 80 int exp_errno; 81 } test_cases[] = { 82 {TESTDIR, ENOTEMPTY}, 83 {longpathname, ENAMETOOLONG}, 84 {TESTDIR2, ENOENT}, 85 {TESTDIR3, ENOTDIR}, 86 #if !defined(UCLINUX) 87 {(char *)-1, EFAULT}, 88 #endif 89 {NULL, EFAULT}, 90 {looppathname, ELOOP}, 91 {TESTDIR5, EROFS}, 92 {MNTPOINT, EBUSY}, 93 }; 94 95 static void setup(void); 96 static void rmdir_verify(struct test_case_t *tc); 97 static void cleanup(void); 98 99 char *TCID = "rmdir02"; 100 int TST_TOTAL = ARRAY_SIZE(test_cases); 101 102 int main(int ac, char **av) 103 { 104 int i, lc; 105 106 tst_parse_opts(ac, av, NULL, NULL); 107 108 setup(); 109 110 for (lc = 0; TEST_LOOPING(lc); lc++) { 111 tst_count = 0; 112 113 for (i = 0; i < TST_TOTAL; i++) 114 rmdir_verify(&test_cases[i]); 115 } 116 117 cleanup(); 118 tst_exit(); 119 } 120 121 static void setup(void) 122 { 123 int i; 124 const char *fs_type; 125 126 tst_require_root(); 127 128 tst_sig(NOFORK, DEF_HANDLER, cleanup); 129 130 TEST_PAUSE; 131 132 tst_tmpdir(); 133 134 fs_type = tst_dev_fs_type(); 135 device = tst_acquire_device(cleanup); 136 137 if (!device) 138 tst_brkm(TCONF, cleanup, "Failed to acquire device"); 139 140 tst_mkfs(cleanup, device, fs_type, NULL, NULL); 141 SAFE_MKDIR(cleanup, MNTPOINT, DIR_MODE); 142 if (mount(device, MNTPOINT, fs_type, 0, NULL) == -1) { 143 tst_brkm(TBROK | TERRNO, cleanup, 144 "mount device:%s failed", device); 145 } 146 SAFE_MKDIR(cleanup, TESTDIR5, DIR_MODE); 147 if (mount(device, MNTPOINT, fs_type, MS_REMOUNT | MS_RDONLY, 148 NULL) == -1) { 149 tst_brkm(TBROK | TERRNO, cleanup, 150 "mount device:%s failed", device); 151 } 152 mount_flag = 1; 153 154 SAFE_MKDIR(cleanup, TESTDIR, DIR_MODE); 155 SAFE_TOUCH(cleanup, TESTFILE, FILE_MODE, NULL); 156 157 memset(longpathname, 'a', PATH_MAX + 1); 158 159 SAFE_TOUCH(cleanup, TESTFILE2, FILE_MODE, NULL); 160 161 #if !defined(UCLINUX) 162 test_cases[4].dir = SAFE_MMAP(cleanup, 0, 1, PROT_NONE, 163 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 164 #endif 165 166 /* 167 * NOTE: the ELOOP test is written based on that the 168 * consecutive symlinks limit in kernel is hardwired 169 * to 40. 170 */ 171 SAFE_MKDIR(cleanup, "loopdir", DIR_MODE); 172 SAFE_SYMLINK(cleanup, "../loopdir", "loopdir/loopdir"); 173 for (i = 0; i < 43; i++) 174 strcat(looppathname, TESTDIR4); 175 } 176 177 static void rmdir_verify(struct test_case_t *tc) 178 { 179 TEST(rmdir(tc->dir)); 180 181 if (TEST_RETURN != -1) { 182 tst_resm(TFAIL, "rmdir() returned %ld, " 183 "expected -1, errno:%d", TEST_RETURN, 184 tc->exp_errno); 185 return; 186 } 187 188 if (TEST_ERRNO == tc->exp_errno) { 189 tst_resm(TPASS | TTERRNO, "rmdir() failed as expected"); 190 } else { 191 tst_resm(TFAIL | TTERRNO, 192 "rmdir() failed unexpectedly; expected: %d - %s", 193 tc->exp_errno, strerror(tc->exp_errno)); 194 } 195 } 196 197 static void cleanup(void) 198 { 199 if (mount_flag && tst_umount(MNTPOINT) == -1) 200 tst_resm(TWARN | TERRNO, "umount %s failed", MNTPOINT); 201 202 if (device) 203 tst_release_device(device); 204 205 tst_rmdir(); 206 } 207