1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 *   Copyright (c) International Business Machines Corp., 2001
4 * Ported to LTP: Wayne Boyer
5 *    06/2017 Modified by Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
6 */
7
8/*
9 * DESCRIPTION
10 *	Open a file with oflag = O_CREAT set, does it set the sticky bit off?
11 *	Open a dir with O_DIRECTORY, does it set the S_IFDIR bit on?
12 *
13 * ALGORITHM
14 *	1. open a new file with O_CREAT, fstat.st_mode should not have the
15 *	   01000 bit on. In Linux, the save text bit is *NOT* cleared.
16 *	2. open a new dir with O_DIRECTORY, fstat.st_mode should have the
17 *	   040000 bit on.
18 */
19
20#define _GNU_SOURCE		/* for O_DIRECTORY */
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <errno.h>
25#include "tst_test.h"
26
27#define TEST_FILE	"testfile"
28#define TEST_DIR	"testdir"
29
30static int fd;
31
32static struct tcase {
33	char *filename;
34	int flag;
35	mode_t mode;
36	unsigned short tst_bit;
37	char *desc;
38} tcases[] = {
39	{TEST_FILE, O_RDWR | O_CREAT, 01444, S_ISVTX, "sticky bit"},
40	{TEST_DIR, O_DIRECTORY, 0, S_IFDIR, "sirectory bit"}
41};
42
43static void verify_open(unsigned int n)
44{
45	struct tcase *tc = &tcases[n];
46	struct stat buf;
47
48	TST_EXP_FD_SILENT(open(tc->filename, tc->flag, tc->mode),
49	           "open() with %s", tc->desc);
50	if (!TST_PASS)
51		return;
52
53	fd = TST_RET;
54
55	SAFE_FSTAT(fd, &buf);
56	if (!(buf.st_mode & tc->tst_bit))
57		tst_res(TFAIL, "%s is cleared unexpectedly", tc->desc);
58	else
59		tst_res(TPASS, "%s is set as expected", tc->desc);
60
61	SAFE_CLOSE(fd);
62	if (S_ISREG(buf.st_mode))
63		SAFE_UNLINK(tc->filename);
64}
65
66static void setup(void)
67{
68	SAFE_MKDIR(TEST_DIR, 0755);
69}
70
71static void cleanup(void)
72{
73	if (fd > 0)
74		SAFE_CLOSE(fd);
75}
76
77static struct tst_test test = {
78	.tcnt = ARRAY_SIZE(tcases),
79	.needs_tmpdir = 1,
80	.setup = setup,
81	.cleanup = cleanup,
82	.test = verify_open,
83};
84