Index: lib/libc/tests/sys/Makefile =================================================================== --- lib/libc/tests/sys/Makefile +++ lib/libc/tests/sys/Makefile @@ -5,6 +5,7 @@ .include ATF_TESTS_C+= queue_test +ATF_TESTS_C+= sendfile_test # TODO: clone, lwp_create, lwp_ctl, posix_fadvise, recvmmsg, # swapcontext Index: lib/libc/tests/sys/sendfile_test.c =================================================================== --- /dev/null +++ lib/libc/tests/sys/sendfile_test.c @@ -25,7 +25,7 @@ */ #include -__FBSDID("$FreeBSD: head/lib/libc/tests/sys/sendfile_test.c 343362 2019-01-23 22:00:17Z ngie $"); +__FBSDID("$FreeBSD: stable/11/lib/libc/tests/sys/sendfile_test.c 343362 2019-01-23 22:00:17Z ngie $"); #include #include @@ -97,24 +97,33 @@ static void resolve_localhost(struct addrinfo **res, int domain, int type, int port) { + const char *host; char *serv; struct addrinfo hints; int error; - ATF_REQUIRE_MSG(domain == AF_INET || domain == AF_INET6, - "unhandled domain: %d", domain); + switch (domain) { + case AF_INET: + host = "127.0.0.1"; + break; + case AF_INET6: + host = "::1"; + break; + default: + atf_tc_fail("unhandled domain: %d", domain); + } ATF_REQUIRE_MSG(asprintf(&serv, "%d", port) >= 0, "asprintf failed: %s", strerror(errno)); memset(&hints, 0, sizeof(hints)); hints.ai_family = domain; - hints.ai_flags = AI_ADDRCONFIG|AI_NUMERICSERV; + hints.ai_flags = AI_ADDRCONFIG|AI_NUMERICSERV|AI_NUMERICHOST; hints.ai_socktype = type; - error = getaddrinfo("localhost", serv, &hints, res); + error = getaddrinfo(host, serv, &hints, res); ATF_REQUIRE_EQ_MSG(error, 0, - "getaddrinfo failed: %s", gai_strerror(errno)); + "getaddrinfo failed: %s", gai_strerror(error)); free(serv); } @@ -147,6 +156,8 @@ "Will try to connect to host='%s', address_family=%d, " "socket_type=%d\n", host, res->ai_family, res->ai_socktype); + /* Avoid a double print when forked by flushing. */ + fflush(stdout); sock = make_socket(res->ai_family, res->ai_socktype, res->ai_protocol); error = connect(sock, (struct sockaddr*)res->ai_addr, res->ai_addrlen); freeaddrinfo(res); @@ -178,6 +189,8 @@ "Will try to bind socket to host='%s', address_family=%d, " "socket_type=%d\n", host, res->ai_family, res->ai_socktype); + /* Avoid a double print when forked by flushing. */ + fflush(stdout); error = bind(sock, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); ATF_REQUIRE_EQ_MSG(error, 0, "bind failed: %s", strerror(errno)); @@ -195,11 +208,17 @@ static void server_cat(const char *dest_filename, int server_sock, size_t len) { - void *buffer; + char *buffer, *buf_window_ptr; int recv_sock; - ssize_t received_bytes; + size_t buffer_size; + ssize_t received_bytes, recv_ret; - buffer = calloc(len + 1, sizeof(char)); + /* + * Ensure that there isn't excess data sent across the wire by + * capturing 10 extra bytes (plus 1 for nul). + */ + buffer_size = len + 10 + 1; + buffer = calloc(buffer_size, sizeof(char)); if (buffer == NULL) err(1, "malloc failed"); @@ -207,32 +226,26 @@ if (recv_sock == -1) err(1, "accept failed"); - /* - * XXX: this assumes the simplest case where all data is received in a - * single recv(2) call. - */ - if (recv(recv_sock, buffer, len, 0) == -1) - err(1, "recv failed"); + buf_window_ptr = buffer; + received_bytes = 0; + do { + recv_ret = recv(recv_sock, buf_window_ptr, + buffer_size - received_bytes, 0); + if (recv_ret <= 0) + break; + buf_window_ptr += recv_ret; + received_bytes += recv_ret; + } while (received_bytes < buffer_size); atf_utils_create_file(dest_filename, "%s", buffer); - /* - * This recv(2) call helps ensure the amount of sent data is exactly - * what was specified by `len`. - */ - received_bytes = recv(recv_sock, buffer, len, 0); - switch (received_bytes) { - case -1: - err(1, "recv failed"); - case 0: - break; - default: - errx(1, "received unexpected data: %s", buffer); - } - (void)close(recv_sock); (void)close(server_sock); free(buffer); + + if (received_bytes != len) + errx(1, "received unexpected data: %zd != %zd", received_bytes, + len); } static int @@ -268,7 +281,7 @@ verify_source_and_dest(const char* dest_filename, int src_fd, off_t offset, size_t nbytes) { - void *dest_pointer, *src_pointer; + char *dest_pointer, *src_pointer; off_t dest_file_size, src_file_size; size_t length; int dest_fd; @@ -290,7 +303,7 @@ ATF_REQUIRE_EQ_MSG(dest_file_size, length, "number of bytes written out to %s (%ju) doesn't match the " - "expected number of bytes (%ju)", dest_filename, dest_file_size, + "expected number of bytes (%zu)", dest_filename, dest_file_size, length); ATF_REQUIRE_EQ_MSG(0, lseek(src_fd, offset, SEEK_SET), @@ -384,7 +397,7 @@ static void fd_positive_shm_test(int domain) { - void *shm_pointer; + char *shm_pointer; off_t offset; size_t nbytes, pattern_size; pid_t server_pid; @@ -658,10 +671,6 @@ offset = 0; nbytes = 0; - atf_tc_expect_fail( - "The header/trailer testcases fail today with a data mismatch; " - "bug # 234809"); - for (i = 0; i < nitems(testcases); i++) { struct sf_hdtr hdtr; char *pattern; @@ -687,9 +696,9 @@ client_sock = setup_tcp_client(domain, port); rc = asprintf(&pattern, "%s%s%s", - testcases[i].include_headers ? headers[0].iov_base : "", + testcases[i].include_headers ? (char *)headers[0].iov_base : "", DETERMINISTIC_PATTERN, - testcases[i].include_trailers ? trailers[0].iov_base : ""); + testcases[i].include_trailers ? (char *)trailers[0].iov_base : ""); ATF_REQUIRE_MSG(rc != -1, "asprintf failed: %s", strerror(errno)); atf_utils_create_file(SOURCE_FILE ".full", "%s", pattern);