1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci * Copyright (c) Wipro Technologies Ltd, 2002.  All Rights Reserved.
3f08c3bdfSopenharmony_ci *  AUTHOR: Nirmala Devi Dhanasekar <nirmala.devi@wipro.com>
4f08c3bdfSopenharmony_ci * Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
5f08c3bdfSopenharmony_ci *
6f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify it
7f08c3bdfSopenharmony_ci * under the terms of version 2 of the GNU General Public License as
8f08c3bdfSopenharmony_ci * published by the Free Software Foundation.
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful, but
11f08c3bdfSopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of
12f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13f08c3bdfSopenharmony_ci *
14f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License along
15f08c3bdfSopenharmony_ci * with this program; if not, write the Free Software Foundation, Inc.,
16f08c3bdfSopenharmony_ci * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17f08c3bdfSopenharmony_ci *
18f08c3bdfSopenharmony_ci */
19f08c3bdfSopenharmony_ci
20f08c3bdfSopenharmony_ci/*
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_ci   DESCRIPTION
23f08c3bdfSopenharmony_ci	Check for basic errors returned by mount(2) system call.
24f08c3bdfSopenharmony_ci
25f08c3bdfSopenharmony_ci	Verify that mount(2) returns -1 and sets errno to
26f08c3bdfSopenharmony_ci	1) ENODEV if filesystem type not configured
27f08c3bdfSopenharmony_ci	2) ENOTBLK if specialfile is not a block device
28f08c3bdfSopenharmony_ci	3) EBUSY if specialfile is already mounted or
29f08c3bdfSopenharmony_ci		it  cannot  be remounted read-only, because it still holds
30f08c3bdfSopenharmony_ci		files open for writing.
31f08c3bdfSopenharmony_ci	4) EINVAL if specialfile or device is invalid or
32f08c3bdfSopenharmony_ci		 a remount was attempted, while source was not already
33f08c3bdfSopenharmony_ci		 mounted on target.
34f08c3bdfSopenharmony_ci	5) EFAULT if specialfile or device file points to invalid address space.
35f08c3bdfSopenharmony_ci	6) ENAMETOOLONG if pathname was longer than MAXPATHLEN.
36f08c3bdfSopenharmony_ci	7) ENOENT if pathname was empty or has a nonexistent component.
37f08c3bdfSopenharmony_ci	8) ENOTDIR if not a directory.
38f08c3bdfSopenharmony_ci*/
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_ci#include <errno.h>
41f08c3bdfSopenharmony_ci#include <sys/mount.h>
42f08c3bdfSopenharmony_ci#include <sys/types.h>
43f08c3bdfSopenharmony_ci#include <sys/stat.h>
44f08c3bdfSopenharmony_ci#include <sys/sysmacros.h>
45f08c3bdfSopenharmony_ci#include <fcntl.h>
46f08c3bdfSopenharmony_ci#include "test.h"
47f08c3bdfSopenharmony_ci#include "safe_macros.h"
48f08c3bdfSopenharmony_ci
49f08c3bdfSopenharmony_cistatic void setup(void);
50f08c3bdfSopenharmony_cistatic void cleanup(void);
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_cichar *TCID = "mount02";
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_ci#define DIR_MODE	(S_IRWXU | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP)
55f08c3bdfSopenharmony_ci#define FILE_MODE	(S_IRWXU | S_IRWXG | S_IRWXO)
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_cistatic char path[PATH_MAX + 2];
58f08c3bdfSopenharmony_cistatic const char *long_path = path;
59f08c3bdfSopenharmony_cistatic const char *fs_type;
60f08c3bdfSopenharmony_cistatic const char *wrong_fs_type = "error";
61f08c3bdfSopenharmony_cistatic const char *mntpoint = "mntpoint";
62f08c3bdfSopenharmony_cistatic const char *device;
63f08c3bdfSopenharmony_cistatic const char *null = NULL;
64f08c3bdfSopenharmony_cistatic const char *fault = (void*)-1;
65f08c3bdfSopenharmony_cistatic const char *nonexistent = "nonexistent";
66f08c3bdfSopenharmony_cistatic const char *char_dev = "char_device";
67f08c3bdfSopenharmony_cistatic const char *file = "filename";
68f08c3bdfSopenharmony_cistatic int fd;
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_cistatic void do_umount(void);
71f08c3bdfSopenharmony_cistatic void close_umount(void);
72f08c3bdfSopenharmony_cistatic void do_mount(void);
73f08c3bdfSopenharmony_cistatic void mount_open(void);
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_cistatic struct test_case {
76f08c3bdfSopenharmony_ci	const char **device;
77f08c3bdfSopenharmony_ci	const char **mntpoint;
78f08c3bdfSopenharmony_ci	const char **fs_type;
79f08c3bdfSopenharmony_ci	unsigned long flag;
80f08c3bdfSopenharmony_ci	int exp_errno;
81f08c3bdfSopenharmony_ci	void (*setup)(void);
82f08c3bdfSopenharmony_ci	void (*cleanup)(void);
83f08c3bdfSopenharmony_ci} tc[] = {
84f08c3bdfSopenharmony_ci	{&device, &mntpoint, &wrong_fs_type, 0, ENODEV, NULL, NULL},
85f08c3bdfSopenharmony_ci	{&char_dev, &mntpoint, &fs_type, 0, ENOTBLK, NULL, NULL},
86f08c3bdfSopenharmony_ci	{&device, &mntpoint, &fs_type, 0, EBUSY, do_mount, do_umount},
87f08c3bdfSopenharmony_ci	{&device, &mntpoint, &fs_type, MS_REMOUNT | MS_RDONLY, EBUSY,
88f08c3bdfSopenharmony_ci	 mount_open, close_umount},
89f08c3bdfSopenharmony_ci	{&null, &mntpoint, &fs_type, 0, EINVAL, NULL, NULL},
90f08c3bdfSopenharmony_ci	{&device, &mntpoint, &null, 0, EINVAL, NULL, NULL},
91f08c3bdfSopenharmony_ci	{&device, &mntpoint, &fs_type, MS_REMOUNT, EINVAL, NULL, NULL},
92f08c3bdfSopenharmony_ci	{&fault, &mntpoint, &fs_type, 0, EFAULT, NULL, NULL},
93f08c3bdfSopenharmony_ci	{&device, &mntpoint, &fault, 0, EFAULT, NULL, NULL},
94f08c3bdfSopenharmony_ci	{&device, &long_path, &fs_type, 0, ENAMETOOLONG, NULL, NULL},
95f08c3bdfSopenharmony_ci	{&device, &nonexistent, &fs_type, 0, ENOENT, NULL, NULL},
96f08c3bdfSopenharmony_ci	{&device, &file, &fs_type, 0, ENOTDIR, NULL, NULL},
97f08c3bdfSopenharmony_ci};
98f08c3bdfSopenharmony_ci
99f08c3bdfSopenharmony_ciint TST_TOTAL = ARRAY_SIZE(tc);
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_cistatic void verify_mount(struct test_case *tc)
102f08c3bdfSopenharmony_ci{
103f08c3bdfSopenharmony_ci	if (tc->setup)
104f08c3bdfSopenharmony_ci		tc->setup();
105f08c3bdfSopenharmony_ci
106f08c3bdfSopenharmony_ci	TEST(mount(*tc->device, *tc->mntpoint, *tc->fs_type, tc->flag, NULL));
107f08c3bdfSopenharmony_ci
108f08c3bdfSopenharmony_ci	if (TEST_RETURN != -1) {
109f08c3bdfSopenharmony_ci		tst_resm(TFAIL, "mount() succeded unexpectedly (ret=%li)",
110f08c3bdfSopenharmony_ci		         TEST_RETURN);
111f08c3bdfSopenharmony_ci		goto cleanup;
112f08c3bdfSopenharmony_ci	}
113f08c3bdfSopenharmony_ci
114f08c3bdfSopenharmony_ci	if (TEST_ERRNO != tc->exp_errno) {
115f08c3bdfSopenharmony_ci		tst_resm(TFAIL | TTERRNO,
116f08c3bdfSopenharmony_ci		         "mount() was expected to fail with %s(%i)",
117f08c3bdfSopenharmony_ci		         tst_strerrno(tc->exp_errno), tc->exp_errno);
118f08c3bdfSopenharmony_ci		goto cleanup;
119f08c3bdfSopenharmony_ci	}
120f08c3bdfSopenharmony_ci
121f08c3bdfSopenharmony_ci	tst_resm(TPASS | TTERRNO, "mount() failed expectedly");
122f08c3bdfSopenharmony_ci
123f08c3bdfSopenharmony_cicleanup:
124f08c3bdfSopenharmony_ci	if (tc->cleanup)
125f08c3bdfSopenharmony_ci		tc->cleanup();
126f08c3bdfSopenharmony_ci}
127f08c3bdfSopenharmony_ci
128f08c3bdfSopenharmony_ciint main(int ac, char **av)
129f08c3bdfSopenharmony_ci{
130f08c3bdfSopenharmony_ci	int lc, i;
131f08c3bdfSopenharmony_ci
132f08c3bdfSopenharmony_ci	tst_parse_opts(ac, av, NULL, NULL);
133f08c3bdfSopenharmony_ci
134f08c3bdfSopenharmony_ci	setup();
135f08c3bdfSopenharmony_ci
136f08c3bdfSopenharmony_ci	for (lc = 0; TEST_LOOPING(lc); lc++) {
137f08c3bdfSopenharmony_ci		tst_count = 0;
138f08c3bdfSopenharmony_ci
139f08c3bdfSopenharmony_ci		for (i = 0; i < TST_TOTAL; ++i)
140f08c3bdfSopenharmony_ci			verify_mount(tc + i);
141f08c3bdfSopenharmony_ci	}
142f08c3bdfSopenharmony_ci
143f08c3bdfSopenharmony_ci	cleanup();
144f08c3bdfSopenharmony_ci	tst_exit();
145f08c3bdfSopenharmony_ci}
146f08c3bdfSopenharmony_ci
147f08c3bdfSopenharmony_cistatic void do_mount(void)
148f08c3bdfSopenharmony_ci{
149f08c3bdfSopenharmony_ci	if (mount(device, mntpoint, fs_type, 0, NULL))
150f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup, "Failed to mount(mntpoint)");
151f08c3bdfSopenharmony_ci}
152f08c3bdfSopenharmony_ci
153f08c3bdfSopenharmony_cistatic void mount_open(void)
154f08c3bdfSopenharmony_ci{
155f08c3bdfSopenharmony_ci	do_mount();
156f08c3bdfSopenharmony_ci
157f08c3bdfSopenharmony_ci	fd = SAFE_OPEN(cleanup, "mntpoint/file", O_CREAT | O_RDWR, S_IRWXU);
158f08c3bdfSopenharmony_ci}
159f08c3bdfSopenharmony_ci
160f08c3bdfSopenharmony_cistatic void close_umount(void)
161f08c3bdfSopenharmony_ci{
162f08c3bdfSopenharmony_ci	SAFE_CLOSE(cleanup, fd);
163f08c3bdfSopenharmony_ci	do_umount();
164f08c3bdfSopenharmony_ci}
165f08c3bdfSopenharmony_ci
166f08c3bdfSopenharmony_cistatic void do_umount(void)
167f08c3bdfSopenharmony_ci{
168f08c3bdfSopenharmony_ci	if (tst_umount(mntpoint))
169f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup, "Failed to umount(mntpoint)");
170f08c3bdfSopenharmony_ci}
171f08c3bdfSopenharmony_ci
172f08c3bdfSopenharmony_cistatic void setup(void)
173f08c3bdfSopenharmony_ci{
174f08c3bdfSopenharmony_ci	dev_t dev;
175f08c3bdfSopenharmony_ci
176f08c3bdfSopenharmony_ci	tst_sig(FORK, DEF_HANDLER, cleanup);
177f08c3bdfSopenharmony_ci
178f08c3bdfSopenharmony_ci	tst_require_root();
179f08c3bdfSopenharmony_ci
180f08c3bdfSopenharmony_ci	tst_tmpdir();
181f08c3bdfSopenharmony_ci
182f08c3bdfSopenharmony_ci	SAFE_TOUCH(cleanup, file, FILE_MODE, NULL);
183f08c3bdfSopenharmony_ci
184f08c3bdfSopenharmony_ci	fs_type = tst_dev_fs_type();
185f08c3bdfSopenharmony_ci	device = tst_acquire_device(cleanup);
186f08c3bdfSopenharmony_ci
187f08c3bdfSopenharmony_ci	if (!device)
188f08c3bdfSopenharmony_ci		tst_brkm(TCONF, cleanup, "Failed to obtain block device");
189f08c3bdfSopenharmony_ci
190f08c3bdfSopenharmony_ci	tst_mkfs(cleanup, device, fs_type, NULL, NULL);
191f08c3bdfSopenharmony_ci
192f08c3bdfSopenharmony_ci	SAFE_MKDIR(cleanup, mntpoint, DIR_MODE);
193f08c3bdfSopenharmony_ci
194f08c3bdfSopenharmony_ci	memset(path, 'a', PATH_MAX + 1);
195f08c3bdfSopenharmony_ci
196f08c3bdfSopenharmony_ci	dev = makedev(1, 3);
197f08c3bdfSopenharmony_ci	if (mknod(char_dev, S_IFCHR | FILE_MODE, dev)) {
198f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup,
199f08c3bdfSopenharmony_ci			 "failed to mknod(char_dev, S_IFCHR | FILE_MODE, %lu)",
200f08c3bdfSopenharmony_ci			 dev);
201f08c3bdfSopenharmony_ci	}
202f08c3bdfSopenharmony_ci
203f08c3bdfSopenharmony_ci	TEST_PAUSE;
204f08c3bdfSopenharmony_ci}
205f08c3bdfSopenharmony_ci
206f08c3bdfSopenharmony_cistatic void cleanup(void)
207f08c3bdfSopenharmony_ci{
208f08c3bdfSopenharmony_ci	if (device)
209f08c3bdfSopenharmony_ci		tst_release_device(device);
210f08c3bdfSopenharmony_ci
211f08c3bdfSopenharmony_ci	tst_rmdir();
212f08c3bdfSopenharmony_ci}
213