Home | History | Annotate | Download | only in umount2
      1 /*
      2  * Copyright (c) 2015 Fujitsu Ltd.
      3  * Author: Guangwen Feng <fenggw-fnst (at) 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 
     37 static void setup(void);
     38 static void test_umount2(int i);
     39 static void verify_failure(int i);
     40 static void verify_success(int i);
     41 static void cleanup(void);
     42 
     43 static const char *device;
     44 static const char *fs_type;
     45 
     46 static int mount_flag;
     47 
     48 static 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 
     59 char *TCID = "umount2_03";
     60 int TST_TOTAL = ARRAY_SIZE(test_cases);
     61 
     62 int 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 
     82 static 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 
    110 static 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 
    129 static 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 
    146 static 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 
    158 static 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