1/* 2 * Copyright (c) 2015 Fujitsu Ltd. 3 * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * You should have received a copy of the GNU General Public License 14 * alone with this program. 15 */ 16 17/* 18 * DESCRIPTION 19 * Test for feature UMOUNT_NOFOLLOW of umount2(). 20 * "Don't dereference target if it is a symbolic link, 21 * and fails with the error EINVAL." 22 */ 23 24#include <errno.h> 25#include <sys/mount.h> 26 27#include "test.h" 28#include "safe_macros.h" 29#include "lapi/mount.h" 30 31#include "umount2.h" 32 33#define DIR_MODE (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) 34#define MNTPOINT "mntpoint" 35#define SYMLINK "symlink" 36 37static void setup(void); 38static void test_umount2(int i); 39static void verify_failure(int i); 40static void verify_success(int i); 41static void cleanup(void); 42 43static const char *device; 44static const char *fs_type; 45 46static int mount_flag; 47 48static struct test_case_t { 49 const char *mntpoint; 50 int exp_errno; 51 const char *desc; 52} test_cases[] = { 53 {SYMLINK, EINVAL, 54 "umount2('symlink', UMOUNT_NOFOLLOW) expected EINVAL"}, 55 {MNTPOINT, 0, 56 "umount2('mntpoint', UMOUNT_NOFOLLOW) expected success"}, 57}; 58 59char *TCID = "umount2_03"; 60int TST_TOTAL = ARRAY_SIZE(test_cases); 61 62int main(int ac, char **av) 63{ 64 int lc; 65 int tc; 66 67 tst_parse_opts(ac, av, NULL, NULL); 68 69 setup(); 70 71 for (lc = 0; TEST_LOOPING(lc); lc++) { 72 tst_count = 0; 73 74 for (tc = 0; tc < TST_TOTAL; tc++) 75 test_umount2(tc); 76 } 77 78 cleanup(); 79 tst_exit(); 80} 81 82static void setup(void) 83{ 84 tst_require_root(); 85 86 if ((tst_kvercmp(2, 6, 34)) < 0) { 87 tst_brkm(TCONF, NULL, "This test can only run on kernels " 88 "that are 2.6.34 or higher"); 89 } 90 91 tst_sig(NOFORK, DEF_HANDLER, NULL); 92 93 tst_tmpdir(); 94 95 fs_type = tst_dev_fs_type(); 96 device = tst_acquire_device(cleanup); 97 98 if (!device) 99 tst_brkm(TCONF, cleanup, "Failed to obtain block device"); 100 101 tst_mkfs(cleanup, device, fs_type, NULL, NULL); 102 103 SAFE_MKDIR(cleanup, MNTPOINT, DIR_MODE); 104 105 SAFE_SYMLINK(cleanup, MNTPOINT, SYMLINK); 106 107 TEST_PAUSE; 108} 109 110static void test_umount2(int i) 111{ 112 SAFE_MOUNT(cleanup, device, MNTPOINT, fs_type, 0, NULL); 113 mount_flag = 1; 114 115 TEST(umount2_retry(test_cases[i].mntpoint, UMOUNT_NOFOLLOW)); 116 117 if (test_cases[i].exp_errno != 0) 118 verify_failure(i); 119 else 120 verify_success(i); 121 122 if (mount_flag) { 123 if (tst_umount(MNTPOINT)) 124 tst_brkm(TBROK, cleanup, "umount() failed"); 125 mount_flag = 0; 126 } 127} 128 129static void verify_failure(int i) 130{ 131 if (TEST_RETURN == 0) { 132 tst_resm(TFAIL, "%s passed unexpectedly", test_cases[i].desc); 133 mount_flag = 0; 134 return; 135 } 136 137 if (TEST_ERRNO != test_cases[i].exp_errno) { 138 tst_resm(TFAIL | TTERRNO, "%s failed unexpectedly", 139 test_cases[i].desc); 140 return; 141 } 142 143 tst_resm(TPASS | TTERRNO, "umount2(2) failed as expected"); 144} 145 146static void verify_success(int i) 147{ 148 if (TEST_RETURN != 0) { 149 tst_resm(TFAIL | TTERRNO, "%s failed unexpectedly", 150 test_cases[i].desc); 151 return; 152 } 153 154 tst_resm(TPASS, "umount2(2) succeeded as expected"); 155 mount_flag = 0; 156} 157 158static void cleanup(void) 159{ 160 if (mount_flag && tst_umount(MNTPOINT)) 161 tst_resm(TWARN | TERRNO, "Failed to unmount"); 162 163 if (device) 164 tst_release_device(device); 165 166 tst_rmdir(); 167} 168