213 lines
5.3 KiB
C
213 lines
5.3 KiB
C
/*
|
|
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
|
|
* AUTHOR: Nirmala Devi Dhanasekar <nirmala.devi@wipro.com>
|
|
* Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of version 2 of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it would be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
|
|
DESCRIPTION
|
|
Check for basic errors returned by mount(2) system call.
|
|
|
|
Verify that mount(2) returns -1 and sets errno to
|
|
1) ENODEV if filesystem type not configured
|
|
2) ENOTBLK if specialfile is not a block device
|
|
3) EBUSY if specialfile is already mounted or
|
|
it cannot be remounted read-only, because it still holds
|
|
files open for writing.
|
|
4) EINVAL if specialfile or device is invalid or
|
|
a remount was attempted, while source was not already
|
|
mounted on target.
|
|
5) EFAULT if specialfile or device file points to invalid address space.
|
|
6) ENAMETOOLONG if pathname was longer than MAXPATHLEN.
|
|
7) ENOENT if pathname was empty or has a nonexistent component.
|
|
8) ENOTDIR if not a directory.
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/sysmacros.h>
|
|
#include <fcntl.h>
|
|
#include "test.h"
|
|
#include "safe_macros.h"
|
|
|
|
static void setup(void);
|
|
static void cleanup(void);
|
|
|
|
char *TCID = "mount02";
|
|
|
|
#define DIR_MODE (S_IRWXU | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP)
|
|
#define FILE_MODE (S_IRWXU | S_IRWXG | S_IRWXO)
|
|
|
|
static char path[PATH_MAX + 2];
|
|
static const char *long_path = path;
|
|
static const char *fs_type;
|
|
static const char *wrong_fs_type = "error";
|
|
static const char *mntpoint = "mntpoint";
|
|
static const char *device;
|
|
static const char *null = NULL;
|
|
static const char *fault = (void*)-1;
|
|
static const char *nonexistent = "nonexistent";
|
|
static const char *char_dev = "char_device";
|
|
static const char *file = "filename";
|
|
static int fd;
|
|
|
|
static void do_umount(void);
|
|
static void close_umount(void);
|
|
static void do_mount(void);
|
|
static void mount_open(void);
|
|
|
|
static struct test_case {
|
|
const char **device;
|
|
const char **mntpoint;
|
|
const char **fs_type;
|
|
unsigned long flag;
|
|
int exp_errno;
|
|
void (*setup)(void);
|
|
void (*cleanup)(void);
|
|
} tc[] = {
|
|
{&device, &mntpoint, &wrong_fs_type, 0, ENODEV, NULL, NULL},
|
|
{&char_dev, &mntpoint, &fs_type, 0, ENOTBLK, NULL, NULL},
|
|
{&device, &mntpoint, &fs_type, 0, EBUSY, do_mount, do_umount},
|
|
{&device, &mntpoint, &fs_type, MS_REMOUNT | MS_RDONLY, EBUSY,
|
|
mount_open, close_umount},
|
|
{&null, &mntpoint, &fs_type, 0, EINVAL, NULL, NULL},
|
|
{&device, &mntpoint, &null, 0, EINVAL, NULL, NULL},
|
|
{&device, &mntpoint, &fs_type, MS_REMOUNT, EINVAL, NULL, NULL},
|
|
{&fault, &mntpoint, &fs_type, 0, EFAULT, NULL, NULL},
|
|
{&device, &mntpoint, &fault, 0, EFAULT, NULL, NULL},
|
|
{&device, &long_path, &fs_type, 0, ENAMETOOLONG, NULL, NULL},
|
|
{&device, &nonexistent, &fs_type, 0, ENOENT, NULL, NULL},
|
|
{&device, &file, &fs_type, 0, ENOTDIR, NULL, NULL},
|
|
};
|
|
|
|
int TST_TOTAL = ARRAY_SIZE(tc);
|
|
|
|
static void verify_mount(struct test_case *tc)
|
|
{
|
|
if (tc->setup)
|
|
tc->setup();
|
|
|
|
TEST(mount(*tc->device, *tc->mntpoint, *tc->fs_type, tc->flag, NULL));
|
|
|
|
if (TEST_RETURN != -1) {
|
|
tst_resm(TFAIL, "mount() succeded unexpectedly (ret=%li)",
|
|
TEST_RETURN);
|
|
goto cleanup;
|
|
}
|
|
|
|
if (TEST_ERRNO != tc->exp_errno) {
|
|
tst_resm(TFAIL | TTERRNO,
|
|
"mount() was expected to fail with %s(%i)",
|
|
tst_strerrno(tc->exp_errno), tc->exp_errno);
|
|
goto cleanup;
|
|
}
|
|
|
|
tst_resm(TPASS | TTERRNO, "mount() failed expectedly");
|
|
|
|
cleanup:
|
|
if (tc->cleanup)
|
|
tc->cleanup();
|
|
}
|
|
|
|
int main(int ac, char **av)
|
|
{
|
|
int lc, i;
|
|
|
|
tst_parse_opts(ac, av, NULL, NULL);
|
|
|
|
setup();
|
|
|
|
for (lc = 0; TEST_LOOPING(lc); lc++) {
|
|
tst_count = 0;
|
|
|
|
for (i = 0; i < TST_TOTAL; ++i)
|
|
verify_mount(tc + i);
|
|
}
|
|
|
|
cleanup();
|
|
tst_exit();
|
|
}
|
|
|
|
static void do_mount(void)
|
|
{
|
|
if (mount(device, mntpoint, fs_type, 0, NULL))
|
|
tst_brkm(TBROK | TERRNO, cleanup, "Failed to mount(mntpoint)");
|
|
}
|
|
|
|
static void mount_open(void)
|
|
{
|
|
do_mount();
|
|
|
|
fd = SAFE_OPEN(cleanup, "mntpoint/file", O_CREAT | O_RDWR, S_IRWXU);
|
|
}
|
|
|
|
static void close_umount(void)
|
|
{
|
|
SAFE_CLOSE(cleanup, fd);
|
|
do_umount();
|
|
}
|
|
|
|
static void do_umount(void)
|
|
{
|
|
if (tst_umount(mntpoint))
|
|
tst_brkm(TBROK | TERRNO, cleanup, "Failed to umount(mntpoint)");
|
|
}
|
|
|
|
static void setup(void)
|
|
{
|
|
dev_t dev;
|
|
|
|
tst_sig(FORK, DEF_HANDLER, cleanup);
|
|
|
|
tst_require_root();
|
|
|
|
tst_tmpdir();
|
|
|
|
SAFE_TOUCH(cleanup, file, FILE_MODE, NULL);
|
|
|
|
fs_type = tst_dev_fs_type();
|
|
device = tst_acquire_device(cleanup);
|
|
|
|
if (!device)
|
|
tst_brkm(TCONF, cleanup, "Failed to obtain block device");
|
|
|
|
tst_mkfs(cleanup, device, fs_type, NULL, NULL);
|
|
|
|
SAFE_MKDIR(cleanup, mntpoint, DIR_MODE);
|
|
|
|
memset(path, 'a', PATH_MAX + 1);
|
|
|
|
dev = makedev(1, 3);
|
|
if (mknod(char_dev, S_IFCHR | FILE_MODE, dev)) {
|
|
tst_brkm(TBROK | TERRNO, cleanup,
|
|
"failed to mknod(char_dev, S_IFCHR | FILE_MODE, %lu)",
|
|
dev);
|
|
}
|
|
|
|
TEST_PAUSE;
|
|
}
|
|
|
|
static void cleanup(void)
|
|
{
|
|
if (device)
|
|
tst_release_device(device);
|
|
|
|
tst_rmdir();
|
|
}
|