Index: stable/12/libexec/tftpd/tests/functional.c =================================================================== --- stable/12/libexec/tftpd/tests/functional.c (revision 348459) +++ stable/12/libexec/tftpd/tests/functional.c (revision 348460) @@ -1,1002 +1,1003 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2018 Alan Somers. All rights reserved. + * Copyright (c) 2018 Alan Somers. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include static const uint16_t BASEPORT = 6969; static const char pidfile[] = "tftpd.pid"; static int protocol = PF_UNSPEC; static int s = -1; /* tftp client socket */ static struct sockaddr_storage addr; /* Destination address for the client */ static bool s_flag = false; /* Pass -s to tftpd */ static bool w_flag = false; /* Pass -w to tftpd */ /* Helper functions*/ static void require_bufeq(const char *expected, ssize_t expected_len, const char *actual, ssize_t len); /* * Receive a response from tftpd * @param hdr The reply's expected header, as a char array * @param contents The reply's expected contents, as a char array * @param contents_len Length of contents */ #define RECV(hdr, contents, contents_len) do { \ char buffer[1024]; \ struct sockaddr_storage from; \ socklen_t fromlen = sizeof(from); \ ssize_t r = recvfrom(s, buffer, sizeof(buffer), 0, \ (struct sockaddr*)&from, &fromlen); \ ATF_REQUIRE(r > 0); \ require_bufeq((hdr), sizeof(hdr), buffer, \ MIN(r, (ssize_t)sizeof(hdr))); \ require_bufeq((const char*) (contents), (contents_len), \ &buffer[sizeof(hdr)], r - sizeof(hdr)); \ if (protocol == PF_INET) { \ ((struct sockaddr_in*)&addr)->sin_port = \ ((struct sockaddr_in*)&from)->sin_port; \ } else { \ ((struct sockaddr_in6*)&addr)->sin6_port = \ ((struct sockaddr_in6*)&from)->sin6_port; \ } \ } while(0) static void recv_ack(uint16_t blocknum) { char hdr[] = {0, 4, blocknum >> 8, blocknum & 0xFF}; RECV(hdr, NULL, 0); } /* * Receive a data packet from tftpd * @param blocknum Expected block number to be received * @param contents Pointer to expected contents * @param contents_len Length of contents expected to receive */ static void recv_data(uint16_t blocknum, const char* contents, size_t contents_len) { char hdr[] = {0, 3, blocknum >> 8, blocknum & 0xFF}; RECV(hdr, contents, contents_len); } #define RECV_ERROR(code, msg) do { \ char hdr[] = {0, 5, code >> 8, code & 0xFF}; \ RECV(hdr, msg, sizeof(msg)); \ } while (0) /* * send a command to tftpd. * @param cmd Command to send, as a char array */ static void send_bytes(const void* cmd, ssize_t len) { ssize_t r; r = sendto(s, cmd, len, 0, (struct sockaddr*)(&addr), addr.ss_len); ATF_REQUIRE_EQ(r, len); } static void send_data(uint16_t blocknum, const char* contents, size_t contents_len) { char buffer[1024]; buffer[0] = 0; /* DATA opcode high byte */ buffer[1] = 3; /* DATA opcode low byte */ buffer[2] = blocknum >> 8; buffer[3] = blocknum & 0xFF; memmove(&buffer[4], contents, contents_len); send_bytes(buffer, 4 + contents_len); } /* * send a command to tftpd. * @param cmd Command to send, as a const string * (terminating NUL will be ignored) */ #define SEND_STR(cmd) ATF_REQUIRE_EQ( \ sendto(s, (cmd), sizeof(cmd) - 1, 0, (struct sockaddr*)(&addr), \ addr.ss_len), \ sizeof(cmd) - 1) /* * Acknowledge block blocknum */ static void send_ack(uint16_t blocknum) { char packet[] = { 0, 4, /* ACK opcode in BE */ blocknum >> 8, blocknum & 0xFF }; send_bytes(packet, sizeof(packet)); } /* * send a read request to tftpd. * @param filename filename as a string, absolute or relative * @param mode either "octet" or "netascii" */ #define SEND_RRQ(filename, mode) SEND_STR("\0\001" filename "\0" mode "\0") /* * send a write request to tftpd. * @param filename filename as a string, absolute or relative * @param mode either "octet" or "netascii" */ #define SEND_WRQ(filename, mode) SEND_STR("\0\002" filename "\0" mode "\0") /* Define a test case, for both IPv4 and IPv6 */ #define TFTPD_TC_DEFINE(name, head, ...) \ static void \ name ## _body(void); \ ATF_TC_WITH_CLEANUP(name ## _v4); \ ATF_TC_HEAD(name ## _v4, tc) \ { \ head \ } \ ATF_TC_BODY(name ## _v4, tc) \ { \ __VA_ARGS__; \ protocol = AF_INET; \ s = setup(&addr, __COUNTER__); \ name ## _body(); \ close(s); \ } \ ATF_TC_CLEANUP(name ## _v4, tc) \ { \ cleanup(); \ } \ ATF_TC_WITH_CLEANUP(name ## _v6); \ ATF_TC_HEAD(name ## _v6, tc) \ { \ head \ } \ ATF_TC_BODY(name ## _v6, tc) \ { \ __VA_ARGS__; \ protocol = AF_INET6; \ s = setup(&addr, __COUNTER__); \ name ## _body(); \ close(s); \ } \ ATF_TC_CLEANUP(name ## _v6, tc) \ { \ cleanup(); \ } \ static void \ name ## _body(void) /* Add the IPv4 and IPv6 versions of a test case */ #define TFTPD_TC_ADD(tp, name ) \ do { \ ATF_TP_ADD_TC(tp, name ## _v4); \ ATF_TP_ADD_TC(tp, name ## _v6); \ } while (0) /* Standard cleanup used by all testcases */ static void cleanup(void) { FILE *f; pid_t pid; f = fopen(pidfile, "r"); if (f == NULL) return; if (fscanf(f, "%d", &pid) == 1) { kill(pid, SIGTERM); waitpid(pid, NULL, 0); } fclose(f); unlink(pidfile); } /* Assert that two binary buffers are identical */ static void require_bufeq(const char *expected, ssize_t expected_len, const char *actual, ssize_t len) { ssize_t i; ATF_REQUIRE_EQ_MSG(expected_len, len, "Expected %zd bytes but got %zd", expected_len, len); for (i = 0; i < len; i++) { ATF_REQUIRE_EQ_MSG(actual[i], expected[i], "Expected %#hhx at position %zd; got %hhx instead", expected[i], i, actual[i]); } } /* * Start tftpd and return its communicating socket * @param to Will be filled in for use with sendto * @param idx Unique identifier of the test case * @return Socket ready to use */ static int setup(struct sockaddr_storage *to, uint16_t idx) { int client_s, server_s, pid, argv_idx; char execname[] = "/usr/libexec/tftpd"; char s_flag_str[] = "-s"; char w_flag_str[] = "-w"; char pwd[MAXPATHLEN]; char *argv[10]; struct sockaddr_in addr4; struct sockaddr_in6 addr6; struct sockaddr *server_addr; struct pidfh *pfh; uint16_t port = BASEPORT + idx; socklen_t len; if (protocol == PF_INET) { len = sizeof(addr4); bzero(&addr4, len); addr4.sin_len = len; addr4.sin_family = PF_INET; addr4.sin_port = htons(port); server_addr = (struct sockaddr*)&addr4; } else { len = sizeof(addr6); bzero(&addr6, len); addr6.sin6_len = len; addr6.sin6_family = PF_INET6; addr6.sin6_port = htons(port); server_addr = (struct sockaddr*)&addr6; } ATF_REQUIRE_EQ(getcwd(pwd, sizeof(pwd)), pwd); /* Must bind(2) pre-fork so it happens before the client's send(2) */ ATF_REQUIRE((server_s = socket(protocol, SOCK_DGRAM, 0)) > 0); ATF_REQUIRE_EQ_MSG(bind(server_s, server_addr, len), 0, "bind failed with error %s", strerror(errno)); pid = fork(); switch (pid) { case -1: atf_tc_fail("fork failed"); break; case 0: /* In child */ pfh = pidfile_open(pidfile, 0644, NULL); ATF_REQUIRE_MSG(pfh != NULL, "pidfile_open: %s", strerror(errno)); ATF_REQUIRE_EQ(pidfile_write(pfh), 0); ATF_REQUIRE_EQ(pidfile_close(pfh), 0); bzero(argv, sizeof(argv)); argv[0] = execname; argv_idx = 1; if (w_flag) argv[argv_idx++] = w_flag_str; if (s_flag) argv[argv_idx++] = s_flag_str; argv[argv_idx++] = pwd; ATF_REQUIRE_EQ(dup2(server_s, STDOUT_FILENO), STDOUT_FILENO); ATF_REQUIRE_EQ(dup2(server_s, STDIN_FILENO), STDIN_FILENO); ATF_REQUIRE_EQ(dup2(server_s, STDERR_FILENO), STDERR_FILENO); execv(execname, argv); atf_tc_fail("exec failed"); break; default: /* In parent */ bzero(to, sizeof(*to)); if (protocol == PF_INET) { struct sockaddr_in *to4 = (struct sockaddr_in*)to; to4->sin_len = sizeof(*to4); to4->sin_family = PF_INET; to4->sin_port = htons(port); to4->sin_addr.s_addr = htonl(INADDR_LOOPBACK); } else { struct in6_addr loopback = IN6ADDR_LOOPBACK_INIT; struct sockaddr_in6 *to6 = (struct sockaddr_in6*)to; to6->sin6_len = sizeof(*to6); to6->sin6_family = PF_INET6; to6->sin6_port = htons(port); to6->sin6_addr = loopback; } close(server_s); ATF_REQUIRE((client_s = socket(protocol, SOCK_DGRAM, 0)) > 0); break; } /* Clear the client's umask. Test cases will specify exact modes */ umask(0000); return (client_s); } /* Like write(2), but never returns less than the requested length */ static void write_all(int fd, const void *buf, size_t nbytes) { ssize_t r; while (nbytes > 0) { r = write(fd, buf, nbytes); ATF_REQUIRE(r > 0); nbytes -= r; buf = (const char*)buf + r; } } /* * Test Cases */ /* * Read a file, specified by absolute pathname. */ TFTPD_TC_DEFINE(abspath,) { int fd; char command[1024]; size_t pathlen; char suffix[] = {'\0', 'o', 'c', 't', 'e', 't', '\0'}; command[0] = 0; /* RRQ high byte */ command[1] = 1; /* RRQ low byte */ ATF_REQUIRE(getcwd(&command[2], sizeof(command) - 2) != NULL); pathlen = strlcat(&command[2], "/abspath.txt", sizeof(command) - 2); ATF_REQUIRE(pathlen + sizeof(suffix) < sizeof(command) - 2); memmove(&command[2 + pathlen], suffix, sizeof(suffix)); fd = open("abspath.txt", O_CREAT | O_RDONLY, 0644); ATF_REQUIRE(fd >= 0); close(fd); send_bytes(command, 2 + pathlen + sizeof(suffix)); recv_data(1, NULL, 0); send_ack(1); } /* * Attempt to read a file outside of the allowed directory(ies) */ TFTPD_TC_DEFINE(dotdot,) { ATF_REQUIRE_EQ(mkdir("subdir", 0777), 0); SEND_RRQ("../disallowed.txt", "octet"); RECV_ERROR(2, "Access violation"); s = setup(&addr, __COUNTER__); \ SEND_RRQ("subdir/../../disallowed.txt", "octet"); RECV_ERROR(2, "Access violation"); s = setup(&addr, __COUNTER__); \ SEND_RRQ("/etc/passwd", "octet"); RECV_ERROR(2, "Access violation"); } /* * With "-s", tftpd should chroot to the specified directory */ TFTPD_TC_DEFINE(s_flag, atf_tc_set_md_var(tc, "require.user", "root");, s_flag = true) { int fd; char contents[] = "small"; fd = open("small.txt", O_RDWR | O_CREAT, 0644); ATF_REQUIRE(fd >= 0); write_all(fd, contents, strlen(contents) + 1); close(fd); SEND_RRQ("/small.txt", "octet"); recv_data(1, contents, strlen(contents) + 1); send_ack(1); } /* * Read a file, and simulate a dropped ACK packet */ TFTPD_TC_DEFINE(rrq_dropped_ack,) { int fd; char contents[] = "small"; fd = open("small.txt", O_RDWR | O_CREAT, 0644); ATF_REQUIRE(fd >= 0); write_all(fd, contents, strlen(contents) + 1); close(fd); SEND_RRQ("small.txt", "octet"); recv_data(1, contents, strlen(contents) + 1); /* * client "sends" the ack, but network drops it * Eventually, tftpd should resend the data packet */ recv_data(1, contents, strlen(contents) + 1); send_ack(1); } /* * Read a file, and simulate a dropped DATA packet */ TFTPD_TC_DEFINE(rrq_dropped_data,) { int fd; size_t i; uint32_t contents[192]; char buffer[1024]; for (i = 0; i < nitems(contents); i++) contents[i] = i; fd = open("medium.txt", O_RDWR | O_CREAT, 0644); ATF_REQUIRE(fd >= 0); write_all(fd, contents, sizeof(contents)); close(fd); SEND_RRQ("medium.txt", "octet"); recv_data(1, (const char*)&contents[0], 512); send_ack(1); (void) recvfrom(s, buffer, sizeof(buffer), 0, NULL, NULL); /* * server "sends" the data, but network drops it * Eventually, client should resend the last ACK */ send_ack(1); recv_data(2, (const char*)&contents[128], 256); send_ack(2); } /* * Read a medium file, and simulate a duplicated ACK packet */ TFTPD_TC_DEFINE(rrq_duped_ack,) { int fd; size_t i; uint32_t contents[192]; for (i = 0; i < nitems(contents); i++) contents[i] = i; fd = open("medium.txt", O_RDWR | O_CREAT, 0644); ATF_REQUIRE(fd >= 0); write_all(fd, contents, sizeof(contents)); close(fd); SEND_RRQ("medium.txt", "octet"); recv_data(1, (const char*)&contents[0], 512); send_ack(1); send_ack(1); /* Dupe an ACK packet */ recv_data(2, (const char*)&contents[128], 256); recv_data(2, (const char*)&contents[128], 256); send_ack(2); } /* * Attempt to read a file without read permissions */ TFTPD_TC_DEFINE(rrq_eaccess,) { int fd; fd = open("empty.txt", O_CREAT | O_RDONLY, 0000); ATF_REQUIRE(fd >= 0); close(fd); SEND_RRQ("empty.txt", "octet"); RECV_ERROR(2, "Access violation"); } /* * Read an empty file */ TFTPD_TC_DEFINE(rrq_empty,) { int fd; fd = open("empty.txt", O_CREAT | O_RDONLY, 0644); ATF_REQUIRE(fd >= 0); close(fd); SEND_RRQ("empty.txt", "octet"); recv_data(1, NULL, 0); send_ack(1); } /* * Read a medium file of more than one block */ TFTPD_TC_DEFINE(rrq_medium,) { int fd; size_t i; uint32_t contents[192]; for (i = 0; i < nitems(contents); i++) contents[i] = i; fd = open("medium.txt", O_RDWR | O_CREAT, 0644); ATF_REQUIRE(fd >= 0); write_all(fd, contents, sizeof(contents)); close(fd); SEND_RRQ("medium.txt", "octet"); recv_data(1, (const char*)&contents[0], 512); send_ack(1); recv_data(2, (const char*)&contents[128], 256); send_ack(2); } /* * Read a file in netascii format */ TFTPD_TC_DEFINE(rrq_netascii,) { int fd; char contents[] = "foo\nbar\rbaz\n"; /* * Weirdly, RFC-764 says that CR must be followed by NUL if a line feed * is not intended */ char expected[] = "foo\r\nbar\r\0baz\r\n"; fd = open("unix.txt", O_RDWR | O_CREAT, 0644); ATF_REQUIRE(fd >= 0); write_all(fd, contents, strlen(contents) + 1); close(fd); SEND_RRQ("unix.txt", "netascii"); recv_data(1, expected, sizeof(expected)); send_ack(1); } /* * Read a file that doesn't exist */ TFTPD_TC_DEFINE(rrq_nonexistent,) { SEND_RRQ("nonexistent.txt", "octet"); RECV_ERROR(1, "File not found"); } /* * Attempt to read a file whose name exceeds PATH_MAX */ TFTPD_TC_DEFINE(rrq_path_max,) { #define AReallyBigFileName \ "AReallyBigFileNameXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ ".txt" ATF_REQUIRE_MSG(strlen(AReallyBigFileName) > PATH_MAX, "Somebody increased PATH_MAX. Update the test"); SEND_RRQ(AReallyBigFileName, "octet"); RECV_ERROR(4, "Illegal TFTP operation"); } /* * Read a small file of less than one block */ TFTPD_TC_DEFINE(rrq_small,) { int fd; char contents[] = "small"; fd = open("small.txt", O_RDWR | O_CREAT, 0644); ATF_REQUIRE(fd >= 0); write_all(fd, contents, strlen(contents) + 1); close(fd); SEND_RRQ("small.txt", "octet"); recv_data(1, contents, strlen(contents) + 1); send_ack(1); } /* * Try to transfer a file with an unknown mode. */ TFTPD_TC_DEFINE(unknown_modes,) { SEND_RRQ("foo.txt", "ascii"); /* Misspelling of "ascii" */ RECV_ERROR(4, "Illegal TFTP operation"); s = setup(&addr, __COUNTER__); \ SEND_RRQ("foo.txt", "binary"); /* Obsolete. Use "octet" instead */ RECV_ERROR(4, "Illegal TFTP operation"); s = setup(&addr, __COUNTER__); \ SEND_RRQ("foo.txt", "en_US.UTF-8"); RECV_ERROR(4, "Illegal TFTP operation"); s = setup(&addr, __COUNTER__); \ SEND_RRQ("foo.txt", "mail"); /* Obsolete in RFC-1350 */ RECV_ERROR(4, "Illegal TFTP operation"); } /* * Send an unknown opcode. tftpd should respond with the appropriate error */ TFTPD_TC_DEFINE(unknown_opcode,) { /* Looks like an RRQ or WRQ request, but with a bad opcode */ SEND_STR("\0\007foo.txt\0octet\0"); RECV_ERROR(4, "Illegal TFTP operation"); } /* * Invoke tftpd with "-w" and write to a nonexistent file. */ TFTPD_TC_DEFINE(w_flag,, w_flag = 1;) { int fd; ssize_t r; char contents[] = "small"; char buffer[1024]; size_t contents_len; contents_len = strlen(contents) + 1; SEND_WRQ("small.txt", "octet"); recv_ack(0); send_data(1, contents, contents_len); recv_ack(1); fd = open("small.txt", O_RDONLY); ATF_REQUIRE(fd >= 0); r = read(fd, buffer, sizeof(buffer)); close(fd); require_bufeq(contents, contents_len, buffer, r); } /* * Write a medium file, and simulate a dropped ACK packet */ TFTPD_TC_DEFINE(wrq_dropped_ack,) { int fd; size_t i; ssize_t r; uint32_t contents[192]; char buffer[1024]; for (i = 0; i < nitems(contents); i++) contents[i] = i; fd = open("medium.txt", O_RDWR | O_CREAT, 0666); ATF_REQUIRE(fd >= 0); close(fd); SEND_WRQ("medium.txt", "octet"); recv_ack(0); send_data(1, (const char*)&contents[0], 512); /* * Servers "sends" an ACK packet, but network drops it. * Eventually, server should resend the last ACK */ (void) recvfrom(s, buffer, sizeof(buffer), 0, NULL, NULL); recv_ack(1); send_data(2, (const char*)&contents[128], 256); recv_ack(2); fd = open("medium.txt", O_RDONLY); ATF_REQUIRE(fd >= 0); r = read(fd, buffer, sizeof(buffer)); close(fd); require_bufeq((const char*)contents, 768, buffer, r); } /* * Write a small file, and simulate a dropped DATA packet */ TFTPD_TC_DEFINE(wrq_dropped_data,) { int fd; ssize_t r; char contents[] = "small"; size_t contents_len; char buffer[1024]; fd = open("small.txt", O_RDWR | O_CREAT, 0666); ATF_REQUIRE(fd >= 0); close(fd); contents_len = strlen(contents) + 1; SEND_WRQ("small.txt", "octet"); recv_ack(0); /* * Client "sends" a DATA packet, but network drops it. * Eventually, server should resend the last ACK */ recv_ack(0); send_data(1, contents, contents_len); recv_ack(1); fd = open("small.txt", O_RDONLY); ATF_REQUIRE(fd >= 0); r = read(fd, buffer, sizeof(buffer)); close(fd); require_bufeq(contents, contents_len, buffer, r); } /* * Write a medium file, and simulate a duplicated DATA packet */ TFTPD_TC_DEFINE(wrq_duped_data,) { int fd; size_t i; ssize_t r; uint32_t contents[192]; char buffer[1024]; for (i = 0; i < nitems(contents); i++) contents[i] = i; fd = open("medium.txt", O_RDWR | O_CREAT, 0666); ATF_REQUIRE(fd >= 0); close(fd); SEND_WRQ("medium.txt", "octet"); recv_ack(0); send_data(1, (const char*)&contents[0], 512); send_data(1, (const char*)&contents[0], 512); recv_ack(1); recv_ack(1); send_data(2, (const char*)&contents[128], 256); recv_ack(2); fd = open("medium.txt", O_RDONLY); ATF_REQUIRE(fd >= 0); r = read(fd, buffer, sizeof(buffer)); close(fd); require_bufeq((const char*)contents, 768, buffer, r); } /* * Attempt to write a file without write permissions */ TFTPD_TC_DEFINE(wrq_eaccess,) { int fd; fd = open("empty.txt", O_CREAT | O_RDONLY, 0440); ATF_REQUIRE(fd >= 0); close(fd); SEND_WRQ("empty.txt", "octet"); RECV_ERROR(2, "Access violation"); } /* * Attempt to write a file without world write permissions, but with world * read permissions */ TFTPD_TC_DEFINE(wrq_eaccess_world_readable,) { int fd; fd = open("empty.txt", O_CREAT | O_RDONLY, 0444); ATF_REQUIRE(fd >= 0); close(fd); SEND_WRQ("empty.txt", "octet"); RECV_ERROR(2, "Access violation"); } /* * Write a medium file of more than one block */ TFTPD_TC_DEFINE(wrq_medium,) { int fd; size_t i; ssize_t r; uint32_t contents[192]; char buffer[1024]; for (i = 0; i < nitems(contents); i++) contents[i] = i; fd = open("medium.txt", O_RDWR | O_CREAT, 0666); ATF_REQUIRE(fd >= 0); close(fd); SEND_WRQ("medium.txt", "octet"); recv_ack(0); send_data(1, (const char*)&contents[0], 512); recv_ack(1); send_data(2, (const char*)&contents[128], 256); recv_ack(2); fd = open("medium.txt", O_RDONLY); ATF_REQUIRE(fd >= 0); r = read(fd, buffer, sizeof(buffer)); close(fd); require_bufeq((const char*)contents, 768, buffer, r); } /* * Write a file in netascii format */ TFTPD_TC_DEFINE(wrq_netascii,) { int fd; ssize_t r; /* * Weirdly, RFC-764 says that CR must be followed by NUL if a line feed * is not intended */ char contents[] = "foo\r\nbar\r\0baz\r\n"; char expected[] = "foo\nbar\rbaz\n"; size_t contents_len; char buffer[1024]; fd = open("unix.txt", O_RDWR | O_CREAT, 0666); ATF_REQUIRE(fd >= 0); close(fd); contents_len = sizeof(contents); SEND_WRQ("unix.txt", "netascii"); recv_ack(0); send_data(1, contents, contents_len); recv_ack(1); fd = open("unix.txt", O_RDONLY); ATF_REQUIRE(fd >= 0); r = read(fd, buffer, sizeof(buffer)); close(fd); require_bufeq(expected, sizeof(expected), buffer, r); } /* * Attempt to write to a nonexistent file. With the default options, this * isn't allowed. */ TFTPD_TC_DEFINE(wrq_nonexistent,) { SEND_WRQ("nonexistent.txt", "octet"); RECV_ERROR(1, "File not found"); } /* * Write a small file of less than one block */ TFTPD_TC_DEFINE(wrq_small,) { int fd; ssize_t r; char contents[] = "small"; size_t contents_len; char buffer[1024]; fd = open("small.txt", O_RDWR | O_CREAT, 0666); ATF_REQUIRE(fd >= 0); close(fd); contents_len = strlen(contents) + 1; SEND_WRQ("small.txt", "octet"); recv_ack(0); send_data(1, contents, contents_len); recv_ack(1); fd = open("small.txt", O_RDONLY); ATF_REQUIRE(fd >= 0); r = read(fd, buffer, sizeof(buffer)); close(fd); require_bufeq(contents, contents_len, buffer, r); } /* * Write an empty file over a non-empty one */ TFTPD_TC_DEFINE(wrq_truncate,) { int fd; char contents[] = "small"; struct stat sb; fd = open("small.txt", O_RDWR | O_CREAT, 0666); ATF_REQUIRE(fd >= 0); write_all(fd, contents, strlen(contents) + 1); close(fd); SEND_WRQ("small.txt", "octet"); recv_ack(0); send_data(1, NULL, 0); recv_ack(1); ATF_REQUIRE_EQ(stat("small.txt", &sb), 0); ATF_REQUIRE_EQ(sb.st_size, 0); } /* * Main */ ATF_TP_ADD_TCS(tp) { TFTPD_TC_ADD(tp, abspath); TFTPD_TC_ADD(tp, dotdot); TFTPD_TC_ADD(tp, s_flag); TFTPD_TC_ADD(tp, rrq_dropped_ack); TFTPD_TC_ADD(tp, rrq_dropped_data); TFTPD_TC_ADD(tp, rrq_duped_ack); TFTPD_TC_ADD(tp, rrq_eaccess); TFTPD_TC_ADD(tp, rrq_empty); TFTPD_TC_ADD(tp, rrq_medium); TFTPD_TC_ADD(tp, rrq_netascii); TFTPD_TC_ADD(tp, rrq_nonexistent); TFTPD_TC_ADD(tp, rrq_path_max); TFTPD_TC_ADD(tp, rrq_small); TFTPD_TC_ADD(tp, unknown_modes); TFTPD_TC_ADD(tp, unknown_opcode); TFTPD_TC_ADD(tp, w_flag); TFTPD_TC_ADD(tp, wrq_dropped_ack); TFTPD_TC_ADD(tp, wrq_dropped_data); TFTPD_TC_ADD(tp, wrq_duped_data); TFTPD_TC_ADD(tp, wrq_eaccess); TFTPD_TC_ADD(tp, wrq_eaccess_world_readable); TFTPD_TC_ADD(tp, wrq_medium); TFTPD_TC_ADD(tp, wrq_netascii); TFTPD_TC_ADD(tp, wrq_nonexistent); TFTPD_TC_ADD(tp, wrq_small); TFTPD_TC_ADD(tp, wrq_truncate); return (atf_no_error()); } Index: stable/12/tests/sys/geom/class/eli/misc_test.sh =================================================================== --- stable/12/tests/sys/geom/class/eli/misc_test.sh (revision 348459) +++ stable/12/tests/sys/geom/class/eli/misc_test.sh (revision 348460) @@ -1,172 +1,173 @@ +# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# # Copyright (c) 2018 Alan Somers -# All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ . $(atf_get_srcdir)/conf.sh atf_test_case preserve_props cleanup preserve_props_head() { atf_set "descr" "geli should preserve basic GEOM properties" atf_set "require.user" "root" atf_set "timeout" 15 } preserve_props_body() { geli_test_setup md=$(attach_md -s1m) atf_check geli onetime /dev/${md} md_secsize=$(diskinfo ${md} | cut -wf 2) md_stripesize=$(diskinfo ${md} | cut -wf 5) eli_secsize=$(diskinfo ${md}.eli | cut -wf 2) eli_stripesize=$(diskinfo ${md}.eli | cut -wf 5) atf_check_equal "$md_secsize" "$eli_secsize" atf_check_equal "$md_stripesize" "$eli_stripesize" } preserve_props_cleanup() { geli_test_cleanup } atf_test_case preserve_disk_props cleanup preserve_disk_props_head() { atf_set "descr" "geli should preserve properties for disks" atf_set "require.user" "root" atf_set "require.config" "disks" atf_set "timeout" 15 } preserve_disk_props_body() { geli_test_setup disks=`atf_config_get disks` disk=${disks%% *} if [ -z "$disk" ]; then atf_skip "Must define disks (see tests(7))" fi atf_check geli onetime ${disk} disk_ident=$(diskinfo -s ${disk}) disk_descr=$(diskinfo -v ${disk} | awk '/Disk descr/ {print $1}') disk_rotrate=$(diskinfo -v ${disk} | awk '/Rotation rate/ {print $1}') disk_zonemode=$(diskinfo -v ${disk} | awk '/Zone Mode/ {print $1}') eli_ident=$(diskinfo -s ${disk}.eli) eli_descr=$(diskinfo -v ${disk}.eli | awk '/Disk descr/ {print $1}') eli_rotrate=$(diskinfo -v ${disk}.eli | awk '/Rotation/ {print $1}') eli_zonemode=$(diskinfo -v ${disk}.eli | awk '/Zone Mode/ {print $1}') atf_check_equal "$disk_ident" "$eli_ident" atf_check_equal "$disk_descr" "$eli_descr" atf_check_equal "$disk_rotrate" "$eli_rotrate" atf_check_equal "$disk_zonemode" "$eli_zonemode" } preserve_disk_props_cleanup() { disk_cleanup geli_test_cleanup } atf_test_case physpath cleanup physpath_head() { atf_set "descr" "geli should append /eli to the underlying device's physical path" atf_set "require.user" "root" atf_set "timeout" 15 } physpath_body() { geli_test_setup if ! error_message=$(geom_load_class_if_needed nop); then atf_skip "$error_message" fi md=$(attach_md -s1m) # If the underlying device has no physical path, then geli should not # create one. atf_check -o empty -e ignore diskinfo -p $md atf_check -s exit:0 geli onetime $md atf_check -o empty -e ignore diskinfo -p $md.eli atf_check -s exit:0 geli kill $md # If the underlying device does have a physical path, then geli should # append "/eli" physpath="some/physical/path" atf_check gnop create -z $physpath ${md} atf_check -s exit:0 geli onetime $md.nop atf_check -o match:"^${physpath}/eli$" diskinfo -p $md.nop.eli } physpath_cleanup() { if [ -f "$TEST_MDS_FILE" ]; then while read md; do [ -c /dev/${md}.nop.eli ] && \ geli detach $md.nop.eli 2>/dev/null [ -c /dev/${md}.nop ] && \ gnop destroy -f $md.nop 2>/dev/null [ -c /dev/${md}.eli ] && \ geli detach $md.eli 2>/dev/null mdconfig -d -u $md 2>/dev/null done < $TEST_MDS_FILE fi true } atf_init_test_cases() { atf_add_test_case physpath atf_add_test_case preserve_props atf_add_test_case preserve_disk_props } common_cleanup() { if [ -f "$MD_DEVS" ]; then while read test_md; do gnop destroy -f ${test_md}.nop 2>/dev/null mdconfig -d -u $test_md 2>/dev/null done < $MD_DEVS rm $MD_DEVS fi if [ -f "$PLAINFILES" ]; then while read f; do rm -f ${f} done < ${PLAINFILES} rm ${PLAINFILES} fi true } disk_cleanup() { disks=`atf_config_get disks` disk=${disks%% *} if [ -n "$disk" ]; then geli kill ${disk} 2>/dev/null fi } Index: stable/12/tests/sys/geom/class/nop/nop_test.sh =================================================================== --- stable/12/tests/sys/geom/class/nop/nop_test.sh (revision 348459) +++ stable/12/tests/sys/geom/class/nop/nop_test.sh (revision 348460) @@ -1,280 +1,281 @@ +# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# # Copyright (c) 2016 Alan Somers -# All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ MD_DEVS="md.devs" PLAINFILES=plainfiles atf_test_case preserve_props cleanup preserve_props_head() { atf_set "descr" "gnop should preserve basic GEOM properties" atf_set "require.user" "root" atf_set "timeout" 15 } preserve_props_body() { load_gnop us=$(alloc_md) atf_check gnop create /dev/${us} md_secsize=$(diskinfo ${us} | cut -wf 2) md_mediasize=$(diskinfo ${us} | cut -wf 3) md_stripesize=$(diskinfo ${us} | cut -wf 5) nop_secsize=$(diskinfo ${us}.nop | cut -wf 2) nop_mediasize=$(diskinfo ${us}.nop | cut -wf 3) nop_stripesize=$(diskinfo ${us}.nop | cut -wf 5) atf_check_equal "$md_secsize" "$nop_secsize" atf_check_equal "$md_mediasize" "$nop_mediasize" atf_check_equal "$md_stripesize" "$nop_stripesize" } preserve_props_cleanup() { common_cleanup } atf_test_case preserve_disk_props cleanup preserve_disk_props_head() { atf_set "descr" "gnop should preserve properties for disks" atf_set "require.user" "root" atf_set "require.config" "disks" atf_set "timeout" 15 } preserve_disk_props_body() { load_gnop disks=`atf_config_get disks` disk=${disks%% *} if [ -z "$disk" ]; then atf_skip "Must define disks (see tests(7))" fi atf_check gnop create ${disk} disk_ident=$(diskinfo -s ${disk}) disk_physpath=$(diskinfo -p ${disk}) disk_descr=$(diskinfo -v ${disk} | awk '/Disk descr/ {print $1}') disk_trim=$(diskinfo -v ${disk} | awk '/TRIM.UNMAP/ {print $1}') disk_rotrate=$(diskinfo -v ${disk} | awk '/Rotation rate/ {print $1}') disk_zonemode=$(diskinfo -v ${disk} | awk '/Zone Mode/ {print $1}') nop_ident=$(diskinfo -s ${disk}.nop) nop_physpath=$(diskinfo -p ${disk}.nop) nop_descr=$(diskinfo -v ${disk}.nop | awk '/Disk descr/ {print $1}') nop_trim=$(diskinfo -v ${disk}.nop | awk '/TRIM.UNMAP/ {print $1}') nop_rotrate=$(diskinfo -v ${disk}.nop | awk '/Rotation/ {print $1}') nop_zonemode=$(diskinfo -v ${disk}.nop | awk '/Zone Mode/ {print $1}') atf_check_equal "$disk_ident" "$nop_ident" atf_check_equal "$disk_physpath" "$nop_physpath" atf_check_equal "$disk_descr" "$nop_descr" atf_check_equal "$disk_trim" "$nop_trim" atf_check_equal "$disk_rotrate" "$nop_rotrate" atf_check_equal "$disk_zonemode" "$nop_zonemode" } preserve_disk_props_cleanup() { disk_cleanup common_cleanup } atf_test_case io cleanup io_head() { atf_set "descr" "I/O works on gnop devices" atf_set "require.user" "root" atf_set "timeout" 15 } io_body() { load_gnop us=$(alloc_md) atf_check gnop create /dev/${us} echo src >> $PLAINFILES echo dst >> $PLAINFILES dd if=/dev/random of=src bs=1m count=1 >/dev/null 2>&1 dd if=src of=/dev/${us}.nop bs=1m count=1 > /dev/null 2>&1 dd if=/dev/${us}.nop of=dst bs=1m count=1 > /dev/null 2>&1 atf_check_equal `md5 -q src` `md5 -q dst` } io_cleanup() { common_cleanup } atf_test_case physpath cleanup physpath_head() { atf_set "descr" "Test gnop's -z option" atf_set "require.user" "root" atf_set "timeout" 15 } physpath_body() { load_gnop us=$(alloc_md) physpath="some/physical/path" atf_check gnop create -z $physpath /dev/${us} gnop_physpath=$(diskinfo -p ${us}.nop) atf_check_equal "$physpath" "$gnop_physpath" } physpath_cleanup() { common_cleanup } atf_test_case physpath_blank cleanup physpath_blank_head() { atf_set "descr" "gnop can set physical path to the empty string" atf_set "require.user" "root" atf_set "require.config" "disks" atf_set "timeout" 15 } physpath_blank_body() { load_gnop disks=`atf_config_get disks` disk=${disks%% *} if [ -z "$disk" ]; then atf_skip "Must define disks (see tests(7))" fi atf_check gnop create -z "" ${disk} gnop_physpath=$(diskinfo -p ${disk}.nop) atf_check_equal "" "$gnop_physpath" } physpath_blank_cleanup() { disk_cleanup common_cleanup } atf_test_case size cleanup size_head() { atf_set "descr" "Test gnop's -s option" atf_set "require.user" "root" atf_set "timeout" 15 } size_body() { load_gnop us=$(alloc_md) for mediasize in 65536 524288 1048576; do atf_check gnop create -s ${mediasize} /dev/${us} gnop_mediasize=`diskinfo /dev/${us}.nop | cut -wf 3` atf_check_equal "${mediasize}" "${gnop_mediasize}" atf_check gnop destroy /dev/${us}.nop done # We shouldn't be able to extend the provider's size atf_check -s not-exit:0 -e ignore gnop create -s 2097152 /dev/${us} } size_cleanup() { common_cleanup } atf_test_case stripesize cleanup stripesize_head() { atf_set "descr" "Test gnop's -p and -P options" atf_set "require.user" "root" atf_set "timeout" 120 } stripesize_body() { load_gnop us=$(alloc_md) for ss in 512 1024 2048 4096 8192; do for sofs in `seq 0 512 ${ss}`; do [ "$sofs" -eq "$ss" ] && continue atf_check gnop create -p ${ss} -P ${sofs} /dev/${us} gnop_ss=`diskinfo /dev/${us}.nop | cut -wf 5` gnop_sofs=`diskinfo /dev/${us}.nop | cut -wf 6` atf_check_equal "${ss}" "${gnop_ss}" atf_check_equal "${sofs}" "${gnop_sofs}" atf_check gnop destroy /dev/${us}.nop done done } stripesize_cleanup() { common_cleanup } atf_init_test_cases() { atf_add_test_case io atf_add_test_case physpath atf_add_test_case physpath_blank atf_add_test_case preserve_props atf_add_test_case preserve_disk_props atf_add_test_case stripesize atf_add_test_case size } alloc_md() { local md md=$(mdconfig -a -t swap -s 1M) || atf_fail "mdconfig -a failed" echo ${md} >> $MD_DEVS echo ${md} } common_cleanup() { if [ -f "$MD_DEVS" ]; then while read test_md; do gnop destroy -f ${test_md}.nop 2>/dev/null mdconfig -d -u $test_md 2>/dev/null done < $MD_DEVS rm $MD_DEVS fi if [ -f "$PLAINFILES" ]; then while read f; do rm -f ${f} done < ${PLAINFILES} rm ${PLAINFILES} fi true } disk_cleanup() { disks=`atf_config_get disks` disk=${disks%% *} if [ -n "$disk" ]; then gnop destroy -f ${disk}.nop 2>/dev/null fi } load_gnop() { if ! kldstat -q -m g_nop; then geom nop load || atf_skip "could not load module for geom nop" fi } Index: stable/12/tests/sys/geom/class/part/misc.sh =================================================================== --- stable/12/tests/sys/geom/class/part/misc.sh (revision 348459) +++ stable/12/tests/sys/geom/class/part/misc.sh (revision 348460) @@ -1,187 +1,188 @@ +# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# # Copyright (c) 2018 Alan Somers -# All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ MD_DEVS="md.devs" atf_test_case blank_physpath cleanup blank_physpath_head() { atf_set "descr" "gpart shouldn't add physical paths to underlying providers that have none" atf_set "require.user" "root" } blank_physpath_body() { load_gnop load_gpart md=$(alloc_md) atf_check -o empty -e ignore diskinfo -p ${md} atf_check -s exit:0 -o ignore gpart create -s bsd ${md} atf_check -s exit:0 -o ignore gpart add -t freebsd-ufs ${md} atf_check -o empty -e ignore diskinfo -p ${md}a } blank_physpath_cleanup() { common_cleanup } atf_test_case bsd_physpath cleanup bsd_physpath_head() { atf_set "descr" "BSD partitions should append /X to the underlying device's physical path" atf_set "require.user" "root" } bsd_physpath_body() { load_gnop load_gpart md=$(alloc_md) physpath="some/physical/path" atf_check gnop create -z $physpath /dev/${md} atf_check -s exit:0 -o ignore gpart create -s bsd ${md}.nop atf_check -s exit:0 -o ignore gpart add -t freebsd-ufs ${md}.nop gpart_physpath=$(diskinfo -p ${md}.nopa) atf_check_equal "${physpath}/a" "$gpart_physpath" } bsd_physpath_cleanup() { common_cleanup } atf_test_case gpt_physpath cleanup gpt_physpath_head() { atf_set "descr" "GPT partitions should append /pX to the underlying device's physical path" atf_set "require.user" "root" } gpt_physpath_body() { load_gnop load_gpart md=$(alloc_md) physpath="some/physical/path" atf_check gnop create -z $physpath /dev/${md} atf_check -s exit:0 -o ignore gpart create -s gpt ${md}.nop atf_check -s exit:0 -o ignore gpart add -t efi ${md}.nop gpart_physpath=$(diskinfo -p ${md}.nopp1) atf_check_equal "${physpath}/p1" "$gpart_physpath" } gpt_physpath_cleanup() { common_cleanup } atf_test_case mbr_physpath cleanup mbr_physpath_head() { atf_set "descr" "MBR partitions should append /sX to the underlying device's physical path" atf_set "require.user" "root" } mbr_physpath_body() { load_gnop load_gpart md=$(alloc_md) physpath="some/physical/path" atf_check gnop create -z $physpath /dev/${md} atf_check -s exit:0 -o ignore gpart create -s mbr ${md}.nop atf_check -s exit:0 -o ignore gpart add -t freebsd ${md}.nop gpart_physpath=$(diskinfo -p ${md}.nops1) atf_check_equal "${physpath}/s1" "$gpart_physpath" } mbr_physpath_cleanup() { common_cleanup } atf_test_case mbr_bsd_physpath cleanup mbr_bsd_physpath_head() { atf_set "descr" "BSD partitions nested within MBR partitions should append /sX/Y to the underlying device's physical path" atf_set "require.user" "root" } mbr_bsd_physpath_body() { load_gnop load_gpart md=$(alloc_md) physpath="some/physical/path" atf_check gnop create -z $physpath /dev/${md} atf_check -s exit:0 -o ignore gpart create -s mbr ${md}.nop atf_check -s exit:0 -o ignore gpart add -t freebsd ${md}.nop atf_check -s exit:0 -o ignore gpart create -s bsd ${md}.nops1 atf_check -s exit:0 -o ignore gpart add -t freebsd-ufs ${md}.nops1 gpart_physpath=$(diskinfo -p ${md}.nops1a) atf_check_equal "${physpath}/s1/a" "$gpart_physpath" } mbr_bsd_physpath_cleanup() { common_cleanup } atf_init_test_cases() { atf_add_test_case blank_physpath atf_add_test_case bsd_physpath atf_add_test_case gpt_physpath atf_add_test_case mbr_physpath atf_add_test_case mbr_bsd_physpath } alloc_md() { local md md=$(mdconfig -a -t swap -s 1M) || atf_fail "mdconfig -a failed" echo ${md} >> $MD_DEVS echo ${md} } common_cleanup() { if [ -f "$MD_DEVS" ]; then while read test_md; do gnop destroy -f ${test_md}.nop 2>/dev/null mdconfig -d -u $test_md 2>/dev/null done < $MD_DEVS rm $MD_DEVS fi true } load_gpart() { if ! kldstat -q -m g_part; then geom part load || atf_skip "could not load module for geom part" fi } load_gnop() { if ! kldstat -q -m g_nop; then geom nop load || atf_skip "could not load module for geom nop" fi } Index: stable/12/tests/sys/kern/unix_socketpair_test.c =================================================================== --- stable/12/tests/sys/kern/unix_socketpair_test.c (revision 348459) +++ stable/12/tests/sys/kern/unix_socketpair_test.c (revision 348460) @@ -1,76 +1,78 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2018 Alan Somers * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include /* getpeereid(3) should work with stream sockets created via socketpair(2) */ ATF_TC_WITHOUT_HEAD(getpeereid); ATF_TC_BODY(getpeereid, tc) { int sv[2]; int s; uid_t real_euid, euid; gid_t real_egid, egid; real_euid = geteuid(); real_egid = getegid(); s = socketpair(PF_LOCAL, SOCK_STREAM, 0, sv); ATF_CHECK_EQ(0, s); ATF_CHECK(sv[0] >= 0); ATF_CHECK(sv[1] >= 0); ATF_CHECK(sv[0] != sv[1]); ATF_REQUIRE_EQ(0, getpeereid(sv[0], &euid, &egid)); ATF_CHECK_EQ(real_euid, euid); ATF_CHECK_EQ(real_egid, egid); ATF_REQUIRE_EQ(0, getpeereid(sv[1], &euid, &egid)); ATF_CHECK_EQ(real_euid, euid); ATF_CHECK_EQ(real_egid, egid); close(sv[0]); close(sv[1]); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, getpeereid); return atf_no_error(); } Index: stable/12/usr.bin/cmp/tests/cmp_test2.sh =================================================================== --- stable/12/usr.bin/cmp/tests/cmp_test2.sh (revision 348459) +++ stable/12/usr.bin/cmp/tests/cmp_test2.sh (revision 348460) @@ -1,66 +1,67 @@ +# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# # Copyright (c) 2017 Alan Somers -# All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # $FreeBSD$ atf_test_case special special_head() { atf_set "descr" "Test cmp(1)'s handling of non-regular files" } special_body() { echo 0123456789abcdef > a echo 0123456789abcdeg > b atf_check -s exit:0 -o empty -e empty -x "cat a | cmp a -" atf_check -s exit:0 -o empty -e empty -x "cat a | cmp - a" atf_check -s exit:1 -o not-empty -e empty -x "cat b | cmp a -" atf_check -s exit:1 -o not-empty -e empty -x "cat b | cmp - a" } atf_test_case symlink symlink_head() { atf_set "descr" "Test cmp(1)'s handling of symlinks" } symlink_body() { echo 0123456789abcdef > a echo 0123456789abcdeg > b ln -s a a.lnk ln -s b b.lnk ln -s a a2.lnk cp a adup ln -s adup adup.lnk atf_check -s exit:0 cmp a a.lnk atf_check -s exit:0 cmp a.lnk a atf_check -s not-exit:0 -o ignore cmp a b.lnk atf_check -s not-exit:0 -o ignore cmp b.lnk a atf_check -s not-exit:0 -o ignore -e ignore cmp -h a a.lnk atf_check -s not-exit:0 -o ignore -e ignore cmp -h a.lnk a atf_check -s exit:0 cmp -h a.lnk a2.lnk atf_check -s not-exit:0 -o ignore -e ignore cmp -h a.lnk adup.lnk } atf_init_test_cases() { atf_add_test_case special atf_add_test_case symlink } Index: stable/12/usr.bin/dc/tests/bcode.sh =================================================================== --- stable/12/usr.bin/dc/tests/bcode.sh (revision 348459) +++ stable/12/usr.bin/dc/tests/bcode.sh (revision 348460) @@ -1,144 +1,143 @@ # SPDX-License-Identifier: BSD-2-Clause-FreeBSD # # Copyright (c) 2017 Alan Somers -# All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ atf_test_case bmod bmod_head() { atf_set "descr" "Tests the remainder % operator" } bmod_body() { cat > input.dc << EOF 0 3 % p # basic usage 1 3 % p 2 3 % p 3 3 % p 4 3 % p _1 3 % p # negative dividends work like a remainder, not a modulo 1 _3 % p # negative divisors use the divisor's absolute value 1k # fractional remainders 5 3 % p 6 5 % p 5.4 3 % p _.1 3 % p 1.1 _3 % p 1 .3 % p EOF dc input.dc > output.txt cat > expect.txt << EOF 0 1 2 0 1 -1 1 2 1 2.4 -.1 1.1 .1 EOF atf_check cmp expect.txt output.txt } atf_test_case bmod_by_zero bmod_by_zero_head() { atf_set "descr" "remaindering by zero should print a warning" } bmod_by_zero_body() { atf_check -e match:"remainder by zero" dc -e '1 0 %' } atf_test_case bdivmod bdivmod_head() { atf_set "descr" "Tests the divide and modulo ~ operator" } bdivmod_body() { cat > input.dc << EOF 0 3 ~ n32Pp # basic usage 1 3 ~ n32Pp 2 3 ~ n32Pp 3 3 ~ n32Pp 4 3 ~ n32Pp _1 3 ~ n32Pp # negative dividends work like a remainder, not a modulo _4 3 ~ n32Pp # sign of quotient and divisor must agree 1 _3 ~ n32Pp # negative divisors use the divisor's absolute value 1k # fractional remainders 5 3 ~ n32Pp 6 5 ~ n32Pp 5.4 3 ~ n32Pp _.1 3 ~ n32Pp 1.1 _3 ~ n32Pp 1 .3 ~ n32Pp 4k .01 .003 ~ n32Pp # divmod quotient always has scale=0 EOF dc input.dc > output.txt cat > expect.txt << EOF 0 0 1 0 2 0 0 1 1 1 -1 0 -1 -1 1 0 2 1.6 1 1.2 2.4 1.8 -.1 0.0 1.1 -.3 .1 3.3 .001 3.3333 EOF atf_check cmp expect.txt output.txt } atf_test_case bdivmod_by_zero bdivmod_by_zero_head() { atf_set "descr" "divmodding by zero should print a warning" } bdivmod_by_zero_body() { atf_check -e match:"divide by zero" dc -e '1 0 ~' } atf_init_test_cases() { atf_add_test_case bmod atf_add_test_case bmod_by_zero atf_add_test_case bdivmod atf_add_test_case bdivmod_by_zero } Index: stable/12/usr.bin/dc/tests/inout.sh =================================================================== --- stable/12/usr.bin/dc/tests/inout.sh (revision 348459) +++ stable/12/usr.bin/dc/tests/inout.sh (revision 348460) @@ -1,102 +1,101 @@ # SPDX-License-Identifier: BSD-2-Clause-FreeBSD # # Copyright (c) 2017 Alan Somers -# All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ atf_test_case base16_input base16_input_head() { atf_set "descr" "Input hexadecimal numbers" } base16_input_body() { cat > input.dc << EOF 4k # set scale to 4 decimal places 16i # switch to base 16 0 p 10 p 1 p 1. p # The '.' should have no effect 1.0 p # Unlike with decimal, should not change the result's scale .8 p # Can input fractions # Check that we can input fractions that need more scale in base 10 than in 16 # See PR 206230 .1 p .10 p # Result should be .0625, with scale=4 .01 p # Result should be truncated to scale=4 8k # Increase scale to 8 places .01 p # Result should be exact again 0.1 p # Leading zeros are ignored 00.1 p # Leading zeros are ignored EOF dc input.dc > output.txt cat > expect.txt << EOF 0 16 1 1 1 .5 .0625 .0625 .0039 .00390625 .0625 .0625 EOF atf_check cmp expect.txt output.txt } atf_test_case base3_input base3_input_head() { atf_set "descr" "Input ternary numbers" } base3_input_body() { cat > input.dc << EOF 4k # 4 digits of precision 3i # Base 3 input 0 p 1 p 10 p .1 p # Repeating fractions get truncated EOF dc input.dc > output.txt cat > expect.txt << EOF 0 1 3 .3333 EOF atf_check cmp expect.txt output.txt } atf_init_test_cases() { atf_add_test_case base16_input atf_add_test_case base3_input } Index: stable/12/usr.bin/pr/tests/basic2_test.sh =================================================================== --- stable/12/usr.bin/pr/tests/basic2_test.sh (revision 348459) +++ stable/12/usr.bin/pr/tests/basic2_test.sh (revision 348460) @@ -1,59 +1,60 @@ +# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# # Copyright (c) 2017 Alan Somers -# All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # $FreeBSD$ atf_test_case across across_head() { atf_set "descr" "Format columns in round-robin order with pr -a" } across_body() { atf_check -s exit:0 -o file:$(atf_get_srcdir)/across.out \ -x "pr -t -a -2 $(atf_get_srcdir)/other.in" } atf_test_case merge merge_head() { atf_set "descr" "Merge two files with pr -m" } merge_body() { atf_check -s ignore -o file:$(atf_get_srcdir)/merge.out \ pr -t -m $(atf_get_srcdir)/d_basic.in $(atf_get_srcdir)/other.in } atf_test_case threecol threecol_head() { atf_set "descr" "Format a file with three columns" } threecol_body() { atf_check -s ignore -o file:$(atf_get_srcdir)/threecol.out \ pr -t -3 $(atf_get_srcdir)/other.in } atf_init_test_cases() { atf_add_test_case across atf_add_test_case merge atf_add_test_case threecol } Index: stable/12/usr.bin/tail/tests/tail_test.sh =================================================================== --- stable/12/usr.bin/tail/tests/tail_test.sh (revision 348459) +++ stable/12/usr.bin/tail/tests/tail_test.sh (revision 348460) @@ -1,291 +1,292 @@ +# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# # Copyright (c) 2016 Alan Somers -# All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ atf_test_case empty_r empty_r_head() { atf_set "descr" "Reverse an empty file" } empty_r_body() { touch infile expectfile tail -r infile > outfile tail -r < infile > outpipe atf_check cmp expectfile outfile atf_check cmp expectfile outpipe } atf_test_case file_r file_r_head() { atf_set "descr" "Reverse a file" } file_r_body() { cat > infile < expectfile << HERE This is the third line This is the second line This is the first line HERE tail -r infile > outfile tail -r < infile > outpipe atf_check cmp expectfile outfile atf_check cmp expectfile outpipe } atf_test_case file_rn2 file_rn2_head() { atf_set "descr" "Reverse the last two lines of a file" } file_rn2_body() { cat > infile < expectfile << HERE This is the third line This is the second line HERE tail -rn2 infile > outfile tail -rn2 < infile > outpipe atf_check cmp expectfile outfile atf_check cmp expectfile outpipe } # Regression test for PR 222671 # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=222671 atf_test_case pipe_leading_newline_r pipe_leading_newline_r_head() { atf_set "descr" "Reverse a pipe whose first character is a newline" } pipe_leading_newline_r_body() { cat > expectfile << HERE 3 2 1 HERE printf '\n1\n2\n3\n' | tail -r > outfile printf '\n1\n2\n3\n' | tail -r > outpipe atf_check cmp expectfile outfile atf_check cmp expectfile outpipe } atf_test_case file_rc28 file_rc28_head() { atf_set "descr" "Reverse a file and display the last 28 characters" } file_rc28_body() { cat > infile < expectfile << HERE This is the third line line HERE tail -rc28 infile > outfile tail -rc28 < infile > outpipe atf_check cmp expectfile outfile atf_check cmp expectfile outpipe } atf_test_case file_rc28 file_rc28_head() { atf_set "descr" "Reverse a file and display the last 28 characters" } file_rc28_body() { cat > infile < expectfile << HERE This is the third line line HERE tail -rc28 infile > outfile tail -rc28 < infile > outpipe atf_check cmp expectfile outfile atf_check cmp expectfile outpipe } atf_test_case longfile_r longfile_r_head() { atf_set "descr" "Reverse a long file" } longfile_r_body() { jot -w "%0511d" 1030 0 > infile jot -w "%0511d" 1030 1029 0 -1 > expectfile tail -r infile > outfile tail -r < infile > outpipe atf_check cmp expectfile outfile atf_check cmp expectfile outpipe } atf_test_case longfile_r_enomem longfile_r_enomem_head() { atf_set "descr" "Reverse a file that's too long to store in RAM" } longfile_r_enomem_body() { # When we reverse a file that's too long for RAM, tail should drop the # first part and just print what it can. We'll check that the last # part is ok { ulimit -v 32768 || atf_skip "Can't adjust ulimit" jot -w "%01023d" 32768 0 | tail -r > outfile ; } if [ "$?" -ne 1 ]; then atf_skip "Didn't get ENOMEM. Adjust test parameters" fi # We don't know how much of the input we dropped. So just check that # the first ten lines of tail's output are the same as the last ten of # the input jot -w "%01023d" 10 32767 0 -1 > expectfile head -n 10 outfile > outtrunc diff expectfile outtrunc atf_check cmp expectfile outtrunc } atf_test_case longfile_r_longlines longfile_r_longlines_head() { atf_set "descr" "Reverse a long file with extremely long lines" } longfile_r_longlines_body() { jot -s " " -w "%07d" 18000 0 > infile jot -s " " -w "%07d" 18000 18000 >> infile jot -s " " -w "%07d" 18000 36000 >> infile jot -s " " -w "%07d" 18000 36000 > expectfile jot -s " " -w "%07d" 18000 18000 >> expectfile jot -s " " -w "%07d" 18000 0 >> expectfile tail -r infile > outfile tail -r < infile > outpipe atf_check cmp expectfile outfile atf_check cmp expectfile outpipe } atf_test_case longfile_rc135782 longfile_rc135782_head() { atf_set "descr" "Reverse a long file and print the last 135,782 bytes" } longfile_rc135782_body() { jot -w "%063d" 9000 0 > infile jot -w "%063d" 2121 8999 0 -1 > expectfile echo "0000000000000000000000000000000006878" >> expectfile tail -rc135782 infile > outfile tail -rc135782 < infile > outpipe atf_check cmp expectfile outfile atf_check cmp expectfile outpipe } atf_test_case longfile_rc145782_longlines longfile_rc145782_longlines_head() { atf_set "descr" "Reverse a long file with extremely long lines and print the last 145,782 bytes" } longfile_rc145782_longlines_body() { jot -s " " -w "%07d" 18000 0 > infile jot -s " " -w "%07d" 18000 18000 >> infile jot -s " " -w "%07d" 18000 36000 >> infile jot -s " " -w "%07d" 18000 36000 > expectfile echo -n "35777 " >> expectfile jot -s " " -w "%07d" 222 35778 >> expectfile tail -rc145782 infile > outfile tail -rc145782 < infile > outpipe atf_check cmp expectfile outfile atf_check cmp expectfile outpipe } atf_test_case longfile_rn2500 longfile_rn2500_head() { atf_set "descr" "Reverse a long file and print the last 2,500 lines" } longfile_rn2500_body() { jot -w "%063d" 9000 0 > infile jot -w "%063d" 2500 8999 0 -1 > expectfile tail -rn2500 infile > outfile tail -rn2500 < infile > outpipe atf_check cmp expectfile outfile atf_check cmp expectfile outpipe } atf_test_case broken_pipe broken_pipe_head() { atf_set "descr" "Do not print bogus errno based output on short writes" } broken_pipe_body() { atf_check -o save:ints seq -f '%128g' 1 1000 atf_check -s ignore \ -e "inline:tail: stdout\nexit code: 1\n" \ -x '(tail -n 856 ints; echo exit code: $? >&2) | sleep 2' } atf_init_test_cases() { atf_add_test_case empty_r atf_add_test_case file_r atf_add_test_case file_rc28 atf_add_test_case file_rn2 atf_add_test_case pipe_leading_newline_r # The longfile tests are designed to exercise behavior in r_buf(), # which operates on 128KB blocks atf_add_test_case longfile_r atf_add_test_case longfile_r_enomem atf_add_test_case longfile_r_longlines atf_add_test_case longfile_rc135782 atf_add_test_case longfile_rc145782_longlines atf_add_test_case longfile_rn2500 atf_add_test_case broken_pipe } Index: stable/12/usr.sbin/fstyp/tests/fstyp_test.sh =================================================================== --- stable/12/usr.sbin/fstyp/tests/fstyp_test.sh (revision 348459) +++ stable/12/usr.sbin/fstyp/tests/fstyp_test.sh (revision 348460) @@ -1,270 +1,271 @@ #!/bin/sh # +# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# # Copyright (c) 2015 Alan Somers -# All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # $FreeBSD$ atf_test_case cd9660 cd9660_head() { atf_set "descr" "fstyp(8) should detect cd9660 filesystems" } cd9660_body() { atf_check -s exit:0 mkdir -p dir/emptydir # makefs requires a nonempty directory atf_check -s exit:0 -o ignore makefs -t cd9660 -Z -s 64m cd9660.img dir atf_check -s exit:0 -o inline:"cd9660\n" fstyp cd9660.img atf_check -s exit:0 -o inline:"cd9660\n" fstyp -l cd9660.img } atf_test_case cd9660_label cd9660_label_head() { atf_set "descr" "fstyp(8) can read the label on a cd9660 filesystem" } cd9660_label_body() { atf_check -s exit:0 mkdir -p dir/emptydir # makefs requires a nonempty directory atf_check -s exit:0 -o ignore makefs -t cd9660 -o label=Foo -Z -s 64m cd9660.img dir atf_check -s exit:0 -o inline:"cd9660\n" fstyp cd9660.img # Note: cd9660 labels are always upper case atf_check -s exit:0 -o inline:"cd9660 FOO\n" fstyp -l cd9660.img } atf_test_case dir dir_head() { atf_set "descr" "fstyp(8) should fail on a directory" } dir_body() { atf_check -s exit:0 mkdir dir atf_check -s exit:1 -e match:"not a disk" fstyp dir } atf_test_case exfat exfat_head() { atf_set "descr" "fstyp(8) can detect exFAT filesystems" } exfat_body() { bzcat $(atf_get_srcdir)/dfr-01-xfat.img.bz2 > exfat.img atf_check -s exit:0 -o inline:"exfat\n" fstyp -u exfat.img } atf_test_case empty empty_head() { atf_set "descr" "fstyp(8) should fail on an empty file" } empty_body() { atf_check -s exit:0 touch empty atf_check -s exit:1 -e match:"filesystem not recognized" fstyp empty } atf_test_case ext2 ext2_head() { atf_set "descr" "fstyp(8) can detect ext2 filesystems" } ext2_body() { bzcat $(atf_get_srcdir)/ext2.img.bz2 > ext2.img atf_check -s exit:0 -o inline:"ext2fs\n" fstyp ext2.img atf_check -s exit:0 -o inline:"ext2fs\n" fstyp -l ext2.img } atf_test_case ext3 ext3_head() { atf_set "descr" "fstyp(8) can detect ext3 filesystems" } ext3_body() { bzcat $(atf_get_srcdir)/ext3.img.bz2 > ext3.img atf_check -s exit:0 -o inline:"ext2fs\n" fstyp ext3.img atf_check -s exit:0 -o inline:"ext2fs\n" fstyp -l ext3.img } atf_test_case ext4 ext4_head() { atf_set "descr" "fstyp(8) can detect ext4 filesystems" } ext4_body() { bzcat $(atf_get_srcdir)/ext4.img.bz2 > ext4.img atf_check -s exit:0 -o inline:"ext2fs\n" fstyp ext4.img atf_check -s exit:0 -o inline:"ext2fs\n" fstyp -l ext4.img } atf_test_case ext4_label ext4_label_head() { atf_set "descr" "fstyp(8) can read the label on an ext4 filesystem" } ext4_label_body() { bzcat $(atf_get_srcdir)/ext4_with_label.img.bz2 > ext4_with_label.img atf_check -s exit:0 -o inline:"ext2fs foo\n" fstyp -l ext4_with_label.img } atf_test_case fat12 fat12_head() { atf_set "descr" "fstyp(8) can detect FAT12 filesystems" } fat12_body() { atf_check -s exit:0 truncate -s 64m msdos.img atf_check -s exit:0 -o ignore -e ignore newfs_msdos -F 12 ./msdos.img atf_check -s exit:0 -o inline:"msdosfs\n" fstyp msdos.img atf_check -s exit:0 -o inline:"msdosfs\n" fstyp -l msdos.img } atf_test_case fat16 fat16_head() { atf_set "descr" "fstyp(8) can detect FAT16 filesystems" } fat16_body() { atf_check -s exit:0 truncate -s 64m msdos.img atf_check -s exit:0 -o ignore -e ignore newfs_msdos -F 16 ./msdos.img atf_check -s exit:0 -o inline:"msdosfs\n" fstyp msdos.img atf_check -s exit:0 -o inline:"msdosfs\n" fstyp -l msdos.img } atf_test_case fat32 fat32_head() { atf_set "descr" "fstyp(8) can detect FAT32 filesystems" } fat32_body() { atf_check -s exit:0 truncate -s 64m msdos.img atf_check -s exit:0 -o ignore -e ignore newfs_msdos -F 32 -c 1 \ ./msdos.img atf_check -s exit:0 -o inline:"msdosfs\n" fstyp msdos.img atf_check -s exit:0 -o inline:"msdosfs\n" fstyp -l msdos.img } atf_test_case fat32_label fat32_label_head() { atf_set "descr" "fstyp(8) can read the label on an msdos filesystem" } fat32_label_body() { atf_check -s exit:0 truncate -s 64m msdos.img atf_check -s exit:0 -o ignore -e ignore newfs_msdos -F 32 -L Foo -c 1 \ ./msdos.img atf_check -s exit:0 -o inline:"msdosfs\n" fstyp msdos.img # Note: msdos labels are always upper case atf_check -s exit:0 -o inline:"msdosfs FOO\n" fstyp -l msdos.img } atf_test_case ntfs ntfs_head() { atf_set "descr" "fstyp(8) can detect ntfs filesystems" } ntfs_body() { bzcat $(atf_get_srcdir)/ntfs.img.bz2 > ntfs.img atf_check -s exit:0 -o inline:"ntfs\n" fstyp ntfs.img atf_check -s exit:0 -o inline:"ntfs\n" fstyp -l ntfs.img } atf_test_case ntfs_with_label ntfs_with_label_head() { atf_set "descr" "fstyp(8) can read labels on ntfs filesystems" } ntfs_with_label_body() { bzcat $(atf_get_srcdir)/ntfs_with_label.img.bz2 > ntfs_with_label.img atf_check -s exit:0 -o inline:"ntfs\n" fstyp ntfs_with_label.img atf_check -s exit:0 -o inline:"ntfs Foo\n" fstyp -l ntfs_with_label.img } atf_test_case ufs1 ufs1_head() { atf_set "descr" "fstyp(8) should detect UFS version 1 filesystems" } ufs1_body() { atf_check -s exit:0 mkdir dir atf_check -s exit:0 -o ignore makefs -Z -s 64m ufs.img dir atf_check -s exit:0 -o inline:"ufs\n" fstyp ufs.img atf_check -s exit:0 -o inline:"ufs\n" fstyp -l ufs.img } atf_test_case ufs2 ufs2_head() { atf_set "descr" "fstyp(8) should detect UFS version 2 filesystems" } ufs2_body() { atf_check -s exit:0 mkdir dir atf_check -s exit:0 -o ignore makefs -o version=2 -Z -s 64m ufs.img dir atf_check -s exit:0 -o inline:"ufs\n" fstyp ufs.img atf_check -s exit:0 -o inline:"ufs\n" fstyp -l ufs.img } atf_test_case ufs2_label ufs2_label_head() { atf_set "descr" "fstyp(8) can read the label on a UFS v2 filesystem" } ufs2_label_body() { atf_check -s exit:0 mkdir dir atf_check -s exit:0 -o ignore makefs -o version=2,label="foo" -Z -s 64m ufs.img dir atf_check -s exit:0 -o inline:"ufs foo\n" fstyp -l ufs.img } atf_test_case ufs_on_device cleanup ufs_on_device_head() { atf_set "descr" "fstyp(8) should work on device nodes" atf_set "require.user" "root" } ufs_on_device_body() { mdconfig -a -t swap -s 64m > mdname md=$(cat mdname) if [ -z "$md" ]; then atf_fail "Failed to create md(4) device" fi atf_check -s exit:0 -o ignore newfs -L foo /dev/$md atf_check -s exit:0 -o inline:"ufs\n" fstyp /dev/$md atf_check -s exit:0 -o inline:"ufs foo\n" fstyp -l /dev/$md } ufs_on_device_cleanup() { md=$(cat mdname) if [ -n "$md" ]; then mdconfig -d -u "$md" fi } atf_test_case zeros zeros_head() { atf_set "descr" "fstyp(8) should fail on a zero-filled file" } zeros_body() { atf_check -s exit:0 truncate -s 256m zeros atf_check -s exit:1 -e match:"filesystem not recognized" fstyp zeros } atf_init_test_cases() { atf_add_test_case cd9660 atf_add_test_case cd9660_label atf_add_test_case dir atf_add_test_case empty atf_add_test_case exfat atf_add_test_case ext2 atf_add_test_case ext3 atf_add_test_case ext4 atf_add_test_case ext4_label atf_add_test_case fat12 atf_add_test_case fat16 atf_add_test_case fat32 atf_add_test_case fat32_label atf_add_test_case ntfs atf_add_test_case ntfs_with_label atf_add_test_case ufs1 atf_add_test_case ufs2 atf_add_test_case ufs2_label atf_add_test_case ufs_on_device atf_add_test_case zeros } Index: stable/12 =================================================================== --- stable/12 (revision 348459) +++ stable/12 (revision 348460) Property changes on: stable/12 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r345034