1/*
2 * Copyright (c) 2013 Fujitsu Ltd.
3 * Author: DAN LI <li.dan@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 along
14 * with this program; if not, write the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 *
17 */
18
19/*
20 *  DESCRIPTION
21 *	Test for feature MS_BIND of mount.
22 *	"Perform a bind mount, making a file or a directory subtree visible
23 *	 at another point within a file system."
24 */
25
26#include <errno.h>
27#include <sys/mount.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
31#include <fcntl.h>
32
33#include "test.h"
34#include "safe_macros.h"
35
36static void help(void);
37static void setup(void);
38static void cleanup(void);
39
40char *TCID = "mount05";
41int TST_TOTAL = 1;
42
43#define DIR_MODE	(S_IRWXU | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP)
44
45static int dflag;
46static char *fstype = "ext2";
47static char *device;
48static const char file_src[] = "mnt_src/tstfile";
49static const char file_des[] = "mnt_des/tstfile";
50static const char mntpoint_src[] = "mnt_src";
51static const char mntpoint_des[] = "mnt_des";
52
53static option_t options[] = {
54	{"T:", NULL, &fstype},
55	{"D:", &dflag, &device},
56	{NULL, NULL, NULL},
57};
58
59int main(int argc, char *argv[])
60{
61	int lc;
62
63	tst_parse_opts(argc, argv, options, &help);
64
65	setup();
66
67	for (lc = 0; TEST_LOOPING(lc); lc++) {
68
69		tst_count = 0;
70
71		TEST(mount(mntpoint_src, mntpoint_des, fstype, MS_BIND, NULL));
72
73		if (TEST_RETURN != 0) {
74			tst_resm(TFAIL | TTERRNO, "mount(2) failed");
75		} else {
76
77			if (open(file_des, O_CREAT | O_EXCL, S_IRWXU) == -1 &&
78			    errno == EEXIST)
79				tst_resm(TPASS, "bind mount is ok");
80			else
81				tst_resm(TFAIL, "file %s is not available",
82					 file_des);
83
84			TEST(tst_umount(mntpoint_des));
85			if (TEST_RETURN != 0)
86				tst_brkm(TBROK | TTERRNO, cleanup,
87					 "umount(2) failed");
88		}
89	}
90
91	cleanup();
92	tst_exit();
93}
94
95void setup(void)
96{
97	tst_require_root();
98
99	tst_sig(NOFORK, DEF_HANDLER, cleanup);
100
101	tst_tmpdir();
102
103	SAFE_MKDIR(cleanup, mntpoint_src, DIR_MODE);
104	SAFE_MKDIR(cleanup, mntpoint_des, DIR_MODE);
105
106	if (dflag) {
107		tst_mkfs(NULL, device, fstype, NULL, NULL);
108
109		SAFE_MOUNT(cleanup, device, mntpoint_src, fstype, 0, NULL);
110	}
111
112	SAFE_FILE_PRINTF(cleanup, file_src, "TEST FILE");
113
114	TEST_PAUSE;
115}
116
117void cleanup(void)
118{
119	if (dflag)
120		if (tst_umount(mntpoint_src) != 0)
121			tst_brkm(TBROK | TTERRNO, NULL, "umount(2) failed");
122
123	tst_rmdir();
124}
125
126void help(void)
127{
128	printf("-T type	  : specifies the type of filesystem to be mounted. "
129	       "Default ext2.\n");
130	printf("-D device : device used for mounting.\n");
131}
132