1/*
2 * Copyright (c) International Business Machines  Corp., 2001
3 * Copyright (c) 2015 Cyril Hrubis <chrubis@suse.cz>
4 *
5 *  07/2001 Ported by Wayne Boyer
6 *  04/2008 Roy Lee <roylee@andestech.com>
7 *
8 * This program is free software;  you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY;  without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
16 * the GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program;  if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23/*
24 * Attempt to execve(2) a file which is being opened by another process for
25 * writing fails with ETXTBSY.
26 */
27
28#ifndef _GNU_SOURCE
29#define _GNU_SOURCE
30#endif
31#include <sys/types.h>
32#include <sys/wait.h>
33#include <errno.h>
34#include <fcntl.h>
35#include <libgen.h>
36#include <stdio.h>
37
38#include "test.h"
39#include "safe_macros.h"
40
41#define TEST_APP "execve_child"
42
43char *TCID = "execve04";
44int TST_TOTAL = 1;
45
46static void setup(void);
47static void cleanup(void);
48static void do_child(void);
49
50int main(int ac, char **av)
51{
52	int lc;
53	pid_t pid;
54	char *argv[2] = {TEST_APP, NULL};
55	char *env[1] = {NULL};
56
57	tst_parse_opts(ac, av, NULL, NULL);
58
59#ifdef UCLINUX
60	maybe_run_child(&do_child, "");
61#endif
62
63	setup();
64
65	for (lc = 0; TEST_LOOPING(lc); lc++) {
66		if ((pid = FORK_OR_VFORK()) == -1) {
67			tst_brkm(TBROK, cleanup, "fork failed");
68		} else if (pid == 0) {
69#ifdef UCLINUX
70			if (self_exec(av[0], "") < 0)
71				tst_brkm(TBROK, cleanup, "self_exec failed");
72#else
73			do_child();
74#endif
75		}
76
77		TST_SAFE_CHECKPOINT_WAIT(cleanup, 0);
78
79		TEST(execve(TEST_APP, argv, env));
80
81		if (TEST_ERRNO != ETXTBSY)
82			tst_resm(TFAIL | TTERRNO, "execve succeeded, expected failure");
83		else
84			tst_resm(TPASS | TTERRNO, "execve failed as expected");
85
86		TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
87		SAFE_WAIT(cleanup, NULL);
88	}
89
90	cleanup();
91	tst_exit();
92}
93
94void setup(void)
95{
96	char path[PATH_MAX];
97
98	if (tst_get_path(TEST_APP, path, sizeof(path))) {
99		tst_brkm(TBROK, NULL,
100		         "Couldn't found "TEST_APP" binary in $PATH");
101	}
102
103	tst_tmpdir();
104
105	TST_CHECKPOINT_INIT(tst_rmdir);
106
107	SAFE_CP(tst_rmdir, path, ".");
108}
109
110static void cleanup(void)
111{
112	tst_rmdir();
113}
114
115static void do_child(void)
116{
117	int fd;
118
119#ifdef UCLINUX
120	TST_CHECKPOINT_INIT(NULL);
121#endif
122
123	if ((fd = open(TEST_APP, O_WRONLY)) == -1) {
124		perror("open failed");
125		exit(1);
126	}
127
128	TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
129
130	exit(0);
131}
132