1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) International Business Machines Corp., 2001
4 * 07/2001 Ported by John George
5 * 04/2002 wjhuie sigset cleanups
6 * 08/2007 Ricardo Salveti de Araujo <rsalveti@linux.vnet.ibm.com>
7 * Copyright (c) Linux Test Project, 2002-2023
8 */
9
10/*\
11 * [Description]
12 *
13 *	Check the return value, and errnos of write(2)
14 *
15 *	- when the file descriptor is invalid - EBADF
16 *	- when the buf parameter is invalid - EFAULT
17 *	- on an attempt to write to a pipe that is not open for reading - EPIPE
18 */
19
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <errno.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <sys/wait.h>
27#include <sys/mman.h>
28#include "tst_test.h"
29
30static int fd;
31static int inv_fd = -1;
32static char b[32];
33static char *buf = b;
34static char *bad_addr;
35static int pipefd[2];
36
37static struct tcase {
38	int *fd;
39	char **buf;
40	size_t size;
41	int exp_errno;
42} tcases[] = {
43	{&inv_fd, &buf, sizeof(buf), EBADF},
44	{&fd, &bad_addr, sizeof(buf), EFAULT},
45	{&pipefd[1], &buf, sizeof(buf), EPIPE},
46};
47
48static volatile int sigpipe_cnt;
49
50static void sighandler(int sig)
51{
52	if (sig == SIGPIPE)
53		sigpipe_cnt++;
54}
55
56static void verify_write(unsigned int i)
57{
58	struct tcase *tc = &tcases[i];
59
60	sigpipe_cnt = 0;
61
62	TST_EXP_FAIL2(write(*tc->fd, *tc->buf, tc->size), tc->exp_errno);
63	if (TST_RET != -1)
64		return;
65
66	if (tc->exp_errno == EPIPE && sigpipe_cnt != 1)
67		tst_res(TFAIL, "sigpipe_cnt = %i", sigpipe_cnt);
68}
69
70static void setup(void)
71{
72	fd = SAFE_OPEN("write_test", O_RDWR | O_CREAT, 0644);
73
74	bad_addr = SAFE_MMAP(0, 1, PROT_NONE,
75			MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
76
77	SAFE_PIPE(pipefd);
78	SAFE_CLOSE(pipefd[0]);
79
80	SAFE_SIGNAL(SIGPIPE, sighandler);
81}
82
83static void cleanup(void)
84{
85	if (fd > 0)
86		SAFE_CLOSE(fd);
87
88	SAFE_MUNMAP(bad_addr, 1);
89}
90
91static struct tst_test test = {
92	.needs_tmpdir = 1,
93	.setup = setup,
94	.cleanup = cleanup,
95	.test = verify_write,
96	.tcnt = ARRAY_SIZE(tcases),
97};
98