1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved. 4 * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com> 5 * 6 * Test Description: 7 * A pipe has a limited capacity. If the pipe with non block mode is full, 8 * then a write(2) will fail and get EAGAIN error. Otherwise, from 1 to 9 * PIPE_BUF bytes may be written. 10 */ 11#define _GNU_SOURCE 12#include <unistd.h> 13#include <stdlib.h> 14#include "tst_test.h" 15#include "lapi/fcntl.h" 16 17static int fds[2]; 18static char *wrbuf; 19static char *rdbuf; 20static ssize_t max_size, invalid_size; 21 22static struct tcase { 23 int full_flag; 24 int offset; 25 char *message; 26 int check_flag; 27} tcases[] = { 28 {1, 0, "Write to full pipe", 1}, 29 /* 30 * For a non-empty(unaligned page size) pipe, the sequent large size 31 * write(>page_size)will use new pages. So it may exist a hole in 32 * page and we print this value instead of checking it. 33 */ 34 {0, 1, "Write to non-empty pipe", 0}, 35 {0, 0, "Write to empty pipe", 1}, 36}; 37 38static void verify_pipe(unsigned int n) 39{ 40 struct tcase *tc = &tcases[n]; 41 int nbytes; 42 43 memset(rdbuf, 0, max_size); 44 45 tst_res(TINFO, "%s", tc->message); 46 if (tc->full_flag) { 47 SAFE_WRITE(SAFE_WRITE_ALL, fds[1], wrbuf, max_size); 48 TEST(write(fds[1], "x", 1)); 49 if (TST_RET != -1) { 50 tst_res(TFAIL, "write succeeded unexpectedly"); 51 goto clean_pipe_buf; 52 } 53 if (TST_ERR == EAGAIN) 54 tst_res(TPASS | TTERRNO, "write failed as expected"); 55 else 56 tst_res(TFAIL | TTERRNO, "write failed, expected EAGAIN but got"); 57 } else { 58 SAFE_WRITE(SAFE_WRITE_ALL, fds[1], "x", tc->offset); 59 TEST(write(fds[1], wrbuf, invalid_size)); 60 if (TST_RET == -1) { 61 tst_res(TFAIL, "write failed unexpectedly"); 62 goto clean_pipe_buf; 63 } 64 tst_res(TPASS, "write succeeded as expectedly"); 65 } 66 SAFE_IOCTL(fds[1], FIONREAD, &nbytes); 67 if (tc->check_flag) { 68 if (nbytes == max_size - tc->offset) 69 tst_res(TPASS, "write %d bytes", nbytes); 70 else 71 tst_res(TFAIL, "write expected %ld bytes, got %d bytes", 72 max_size, nbytes); 73 } else 74 tst_res(TPASS, "write %d bytes", nbytes); 75 76clean_pipe_buf: 77 SAFE_READ(0, fds[0], rdbuf, max_size); 78} 79 80 81static void cleanup(void) 82{ 83 if (fds[0] > 0) 84 SAFE_CLOSE(fds[0]); 85 if (fds[1] > 0) 86 SAFE_CLOSE(fds[1]); 87 if (wrbuf) 88 free(wrbuf); 89 if (rdbuf) 90 free(rdbuf); 91} 92 93static void setup(void) 94{ 95 SAFE_PIPE(fds); 96 97 max_size = SAFE_FCNTL(fds[1], F_GETPIPE_SZ); 98 invalid_size = max_size + 4096; 99 wrbuf = SAFE_MALLOC(invalid_size); 100 rdbuf = SAFE_MALLOC(max_size); 101 memset(wrbuf, 'x', invalid_size); 102 103 SAFE_FCNTL(fds[1], F_SETFL, O_NONBLOCK); 104 SAFE_FCNTL(fds[0], F_SETFL, O_NONBLOCK); 105} 106 107static struct tst_test test = { 108 .test = verify_pipe, 109 .setup = setup, 110 .cleanup = cleanup, 111 .tcnt = ARRAY_SIZE(tcases), 112}; 113