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