blob: a04c834a14868da20bb07f08ce67ba7b27a51108 [file] [log] [blame]
/*
* Copyright (C) 2013 Red Hat, Inc.
*
* 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.
*
* Further, this software is distributed without any warranty that it
* is free of the rightful claim of any third person regarding
* infringement or the like. Any license provided herein, whether
* implied or otherwise, applies only to this software file. Patent
* licenses, if any, provided herein do not apply to combinations of
* this program with other software, or any other product whatsoever.
*
* 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.
*/
/*
* 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 "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "test.h"
char *TCID = "open11";
/* Define test files */
#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 "t_dev" /* test device special file */
#define T_MSG "this is a test string"
static void setup(void);
static void cleanup(void);
struct test_case {
char *desc;
char *path;
int flags;
mode_t mode;
int err;
};
struct test_case 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,
},
};
int TST_TOTAL = sizeof(tc) / sizeof(tc[0]);
int main(int argc, char *argv[])
{
int lc;
int i;
int fd;
int ret;
const char *msg;
msg = parse_opts(argc, argv, NULL, NULL);
if (msg != NULL)
tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg);
setup();
for (lc = 0; TEST_LOOPING(lc); lc++) {
for (i = 0; i < TST_TOTAL; i++) {
TEST(open(tc[i].path, tc[i].flags, tc[i].mode));
fd = TEST_RETURN;
if (tc[i].err == -1 || TEST_ERRNO == tc[i].err) {
tst_resm(TPASS, "%s", tc[i].desc);
} else {
tst_resm(TFAIL | TTERRNO,
"%s - expected errno %d - Got",
tc[i].desc, tc[i].err);
}
if (fd > 0) {
ret = close(fd);
if (ret < 0)
tst_resm(TWARN, "%s - close failed: %s",
tc[i].desc, strerror(errno));
}
}
}
cleanup();
tst_exit();
}
static void setup(void)
{
int fd;
int ret;
tst_require_root(NULL);
tst_tmpdir();
/* Create test files */
fd = open(T_REG, O_WRONLY | O_CREAT, 0644);
if (fd == -1)
tst_brkm(TBROK | TERRNO, cleanup, "Create %s failed", T_REG);
ret = write(fd, T_MSG, sizeof(T_MSG));
if (ret == -1) {
close(fd);
tst_brkm(TBROK | TERRNO, cleanup, "Write %s failed", T_REG);
}
close(fd);
fd = creat(T_REG_EMPTY, 0644);
if (fd == -1)
tst_brkm(TBROK | TERRNO, cleanup, "Create %s failed",
T_REG_EMPTY);
close(fd);
ret = link(T_REG, T_LINK_REG);
if (ret == -1)
tst_brkm(TBROK | TERRNO, cleanup, "Hard link %s -> %s failed",
T_REG, T_LINK_REG);
ret = symlink(T_REG, T_SYMLINK_REG);
if (ret == -1)
tst_brkm(TBROK | TERRNO, cleanup, "Symlink %s -> %s failed",
T_REG, T_SYMLINK_REG);
ret = mkdir(T_DIR, 0755);
if (ret == -1)
tst_brkm(TBROK | TERRNO, cleanup, "mkdir %s failed", T_DIR);
ret = symlink(T_DIR, T_SYMLINK_DIR);
if (ret == -1)
tst_brkm(TBROK | TERRNO, cleanup, "Symlink %s -> %s failed",
T_DIR, T_SYMLINK_DIR);
ret = mknod(T_DEV, S_IFCHR, makedev(1, 5));
if (ret == -1)
tst_brkm(TBROK | TERRNO, cleanup, "Create char dev %s failed",
T_DEV);
TEST_PAUSE;
}
static void cleanup(void)
{
tst_rmdir();
}