324 lines
8.2 KiB
C
324 lines
8.2 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright (C) 2013 Red Hat, Inc.
|
|
*
|
|
* Basic tests for open(2) and make sure open(2) works and handles error
|
|
* conditions correctly.
|
|
*
|
|
* There are 28 test cases:
|
|
* 1. Open regular file O_RDONLY
|
|
* 2. Open regular file O_WRONLY
|
|
* 3. Open regular file O_RDWR
|
|
* 4. Open regular file O_RDWR | O_SYNC
|
|
* 5. Open regular file O_RDWR | O_TRUNC
|
|
* 6. Open dir O_RDONLY
|
|
* 7. Open dir O_RDWR, expect EISDIR
|
|
* 8. Open regular file O_DIRECTORY, expect ENOTDIR
|
|
* 9. Open hard link file O_RDONLY
|
|
* 10. Open hard link file O_WRONLY
|
|
* 11. Open hard link file O_RDWR
|
|
* 12. Open sym link file O_RDONLY
|
|
* 13. Open sym link file O_WRONLY
|
|
* 14. Open sym link file O_RDWR
|
|
* 15. Open sym link dir O_RDONLY
|
|
* 16. Open sym link dir O_WRONLY, expect EISDIR
|
|
* 17. Open sym link dir O_RDWR, expect EISDIR
|
|
* 18. Open device special file O_RDONLY
|
|
* 19. Open device special file O_WRONLY
|
|
* 20. Open device special file O_RDWR
|
|
* 21. Open non-existing regular file in existing dir
|
|
* 22. Open link file O_RDONLY | O_CREAT
|
|
* 23. Open symlink file O_RDONLY | O_CREAT
|
|
* 24. Open regular file O_RDONLY | O_CREAT
|
|
* 25. Open symlink dir O_RDONLY | O_CREAT, expect EISDIR
|
|
* 26. Open dir O_RDONLY | O_CREAT, expect EISDIR
|
|
* 27. Open regular file O_RDONLY | O_TRUNC, behaviour is undefined but should
|
|
* not oops or hang
|
|
* 28. Open regular file(non-empty) O_RDONLY | O_TRUNC, behaviour is undefined
|
|
* but should not oops or hang
|
|
*/
|
|
|
|
#define _GNU_SOURCE
|
|
#include <errno.h>
|
|
#include <sys/sysmacros.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
#include "tst_test.h"
|
|
|
|
#define MNTPOINT "mntpoint"
|
|
#define T_REG "t_reg" /* regular file with content */
|
|
#define T_REG_EMPTY "t_reg_empty" /* empty regular file */
|
|
#define T_LINK_REG "t_link_reg" /* hard link to T_REG */
|
|
#define T_NEW_REG "t_new_reg" /* new regular file to be created */
|
|
#define T_SYMLINK_REG "t_symlink_reg" /* symlink to T_REG */
|
|
#define T_DIR "t_dir" /* test dir */
|
|
#define T_SYMLINK_DIR "t_symlink_dir" /* symlink to T_DIR */
|
|
#define T_DEV MNTPOINT"/t_dev" /* test device special file */
|
|
|
|
#define T_MSG "this is a test string"
|
|
|
|
static struct test_case {
|
|
char *desc;
|
|
char *path;
|
|
int flags;
|
|
mode_t mode;
|
|
int err;
|
|
} tc[] = {
|
|
/* Test open(2) regular file */
|
|
{ /* open regular file O_RDONLY */
|
|
.desc = "Open regular file O_RDONLY",
|
|
.path = T_REG_EMPTY,
|
|
.flags = O_RDONLY,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
{ /* open regular file O_WRONLY */
|
|
.desc = "Open regular file O_WRONLY",
|
|
.path = T_REG_EMPTY,
|
|
.flags = O_WRONLY,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
{ /* open regular file O_RDWR */
|
|
.desc = "Open regular file O_RDWR",
|
|
.path = T_REG_EMPTY,
|
|
.flags = O_RDWR,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
{ /* open regular file O_RDWR | O_SYNC*/
|
|
.desc = "Open regular file O_RDWR | O_SYNC",
|
|
.path = T_REG_EMPTY,
|
|
.flags = O_RDWR | O_SYNC,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
{ /* open regular file O_RDWR | O_TRUNC */
|
|
.desc = "Open regular file O_RDWR | O_TRUNC",
|
|
.path = T_REG_EMPTY,
|
|
.flags = O_RDWR | O_TRUNC,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
/* Test open(2) directory */
|
|
{ /* open dir O_RDONLY */
|
|
.desc = "Open dir O_RDONLY",
|
|
.path = T_DIR,
|
|
.flags = O_RDONLY,
|
|
.mode = 0755,
|
|
.err = 0,
|
|
},
|
|
{ /* open dir O_RDWR */
|
|
.desc = "Open dir O_RDWR, expect EISDIR",
|
|
.path = T_DIR,
|
|
.flags = O_RDWR,
|
|
.mode = 0755,
|
|
.err = EISDIR,
|
|
},
|
|
{ /* open regular file O_DIRECTORY */
|
|
.desc = "Open regular file O_DIRECTORY, expect ENOTDIR",
|
|
.path = T_REG_EMPTY,
|
|
.flags = O_RDONLY | O_DIRECTORY,
|
|
.mode = 0644,
|
|
.err = ENOTDIR,
|
|
},
|
|
/* Test open(2) hard link */
|
|
{ /* open hard link file O_RDONLY */
|
|
.desc = "Open hard link file O_RDONLY",
|
|
.path = T_LINK_REG,
|
|
.flags = O_RDONLY,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
{ /* open hard link file O_WRONLY */
|
|
.desc = "Open hard link file O_WRONLY",
|
|
.path = T_LINK_REG,
|
|
.flags = O_WRONLY,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
{ /* open hard link file O_RDWR */
|
|
.desc = "Open hard link file O_RDWR",
|
|
.path = T_LINK_REG,
|
|
.flags = O_RDWR,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
/* Test open(2) sym link */
|
|
{ /* open sym link file O_RDONLY */
|
|
.desc = "Open sym link file O_RDONLY",
|
|
.path = T_SYMLINK_REG,
|
|
.flags = O_RDONLY,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
{ /* open sym link file O_WRONLY */
|
|
.desc = "Open sym link file O_WRONLY",
|
|
.path = T_SYMLINK_REG,
|
|
.flags = O_WRONLY,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
{ /* open sym link file O_RDWR */
|
|
.desc = "Open sym link file O_RDWR",
|
|
.path = T_SYMLINK_REG,
|
|
.flags = O_RDWR,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
{ /* open sym link dir O_RDONLY */
|
|
.desc = "Open sym link dir O_RDONLY",
|
|
.path = T_SYMLINK_DIR,
|
|
.flags = O_RDONLY,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
{ /* open sym link dir O_WRONLY */
|
|
.desc = "Open sym link dir O_WRONLY, expect EISDIR",
|
|
.path = T_SYMLINK_DIR,
|
|
.flags = O_WRONLY,
|
|
.mode = 0644,
|
|
.err = EISDIR,
|
|
},
|
|
{ /* open sym link dir O_RDWR */
|
|
.desc = "Open sym link dir O_RDWR, expect EISDIR",
|
|
.path = T_SYMLINK_DIR,
|
|
.flags = O_RDWR,
|
|
.mode = 0644,
|
|
.err = EISDIR,
|
|
},
|
|
/* * Test open(2) device special */
|
|
{ /* open device special file O_RDONLY */
|
|
.desc = "Open device special file O_RDONLY",
|
|
.path = T_DEV,
|
|
.flags = O_RDONLY,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
{ /* open device special file O_WRONLY */
|
|
.desc = "Open device special file O_WRONLY",
|
|
.path = T_DEV,
|
|
.flags = O_WRONLY,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
{ /* open device special file O_RDWR */
|
|
.desc = "Open device special file O_RDWR",
|
|
.path = T_DEV,
|
|
.flags = O_RDWR,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
/* * Test open(2) non-existing file */
|
|
{ /* open non-existing regular file in existing dir */
|
|
.desc = "Open non-existing regular file in existing dir",
|
|
.path = T_DIR"/"T_NEW_REG,
|
|
.flags = O_RDWR | O_CREAT,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
/* test open(2) with O_CREAT */
|
|
{ /* open hard link file O_RDONLY | O_CREAT */
|
|
.desc = "Open link file O_RDONLY | O_CREAT",
|
|
.path = T_LINK_REG,
|
|
.flags = O_RDONLY | O_CREAT,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
{ /* open sym link file O_RDONLY | O_CREAT */
|
|
.desc = "Open symlink file O_RDONLY | O_CREAT",
|
|
.path = T_SYMLINK_REG,
|
|
.flags = O_RDONLY | O_CREAT,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
{ /* open regular file O_RDONLY | O_CREAT */
|
|
.desc = "Open regular file O_RDONLY | O_CREAT",
|
|
.path = T_REG_EMPTY,
|
|
.flags = O_RDONLY | O_CREAT,
|
|
.mode = 0644,
|
|
.err = 0,
|
|
},
|
|
{ /* open symlink dir O_RDONLY | O_CREAT */
|
|
.desc = "Open symlink dir O_RDONLY | O_CREAT, expect EISDIR",
|
|
.path = T_SYMLINK_DIR,
|
|
.flags = O_RDONLY | O_CREAT,
|
|
.mode = 0644,
|
|
.err = EISDIR,
|
|
},
|
|
{ /* open dir O_RDONLY | O_CREAT */
|
|
.desc = "Open dir O_RDONLY | O_CREAT, expect EISDIR",
|
|
.path = T_DIR,
|
|
.flags = O_RDONLY | O_CREAT,
|
|
.mode = 0644,
|
|
.err = EISDIR,
|
|
},
|
|
/* Other random open(2) tests */
|
|
{ /* open regular file O_RDONLY | O_TRUNC */
|
|
.desc = "Open regular file O_RDONLY | O_TRUNC, "
|
|
"behaviour is undefined but should not oops or hang",
|
|
.path = T_REG_EMPTY,
|
|
.flags = O_RDONLY | O_TRUNC,
|
|
.mode = 0644,
|
|
.err = -1,
|
|
},
|
|
{ /* open regular(non-empty) file O_RDONLY | O_TRUNC */
|
|
.desc = "Open regular file(non-empty) O_RDONLY | O_TRUNC, "
|
|
"behaviour is undefined but should not oops or hang",
|
|
.path = T_REG,
|
|
.flags = O_RDONLY | O_TRUNC,
|
|
.mode = 0644,
|
|
.err = -1,
|
|
},
|
|
};
|
|
|
|
static void verify_open(unsigned int n)
|
|
{
|
|
if (tc[n].err > 0) {
|
|
TST_EXP_FAIL(open(tc[n].path, tc[n].flags, tc[n].mode),
|
|
tc[n].err, "%s", tc[n].desc);
|
|
} else if (tc[n].err == 0) {
|
|
TST_EXP_FD(open(tc[n].path, tc[n].flags, tc[n].mode),
|
|
"%s", tc[n].desc);
|
|
} else {
|
|
TEST(open(tc[n].path, tc[n].flags, tc[n].mode));
|
|
tst_res(TPASS, "%s", tc[n].desc);
|
|
}
|
|
|
|
if (TST_RET > 0)
|
|
SAFE_CLOSE(TST_RET);
|
|
}
|
|
|
|
static void setup(void)
|
|
{
|
|
int fd;
|
|
int ret;
|
|
|
|
fd = SAFE_OPEN(T_REG, O_WRONLY | O_CREAT, 0644);
|
|
ret = write(fd, T_MSG, sizeof(T_MSG));
|
|
if (ret == -1) {
|
|
SAFE_CLOSE(fd);
|
|
tst_brk(TBROK | TERRNO, "Write %s failed", T_REG);
|
|
}
|
|
SAFE_CLOSE(fd);
|
|
|
|
SAFE_TOUCH(T_REG_EMPTY, 0644, NULL);
|
|
SAFE_LINK(T_REG, T_LINK_REG);
|
|
SAFE_SYMLINK(T_REG, T_SYMLINK_REG);
|
|
SAFE_MKDIR(T_DIR, 0755);
|
|
SAFE_SYMLINK(T_DIR, T_SYMLINK_DIR);
|
|
SAFE_MKNOD(T_DEV, S_IFCHR, makedev(1, 5));
|
|
}
|
|
|
|
static struct tst_test test = {
|
|
.tcnt = ARRAY_SIZE(tc),
|
|
.setup = setup,
|
|
.test = verify_open,
|
|
.needs_devfs = 1,
|
|
.mntpoint = MNTPOINT,
|
|
.needs_root = 1,
|
|
};
|