141a3b124SEnji Cooper /*- 241a3b124SEnji Cooper Copyright (C) 2013 Pietro Cerutti <gahr@FreeBSD.org> 341a3b124SEnji Cooper 441a3b124SEnji Cooper Redistribution and use in source and binary forms, with or without 541a3b124SEnji Cooper modification, are permitted provided that the following conditions 641a3b124SEnji Cooper are met: 741a3b124SEnji Cooper 1. Redistributions of source code must retain the above copyright 841a3b124SEnji Cooper notice, this list of conditions and the following disclaimer. 941a3b124SEnji Cooper 2. Redistributions in binary form must reproduce the above copyright 1041a3b124SEnji Cooper notice, this list of conditions and the following disclaimer in the 1141a3b124SEnji Cooper documentation and/or other materials provided with the distribution. 1241a3b124SEnji Cooper 1341a3b124SEnji Cooper THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1441a3b124SEnji Cooper ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1541a3b124SEnji Cooper IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1641a3b124SEnji Cooper ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 1741a3b124SEnji Cooper FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1841a3b124SEnji Cooper DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1941a3b124SEnji Cooper OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2041a3b124SEnji Cooper HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2141a3b124SEnji Cooper LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2241a3b124SEnji Cooper OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2341a3b124SEnji Cooper SUCH DAMAGE. 2441a3b124SEnji Cooper */ 2541a3b124SEnji Cooper 2641a3b124SEnji Cooper /* 2741a3b124SEnji Cooper * Test basic FILE * functions (fread, fwrite, fseek, fclose) against 2841a3b124SEnji Cooper * a FILE * retrieved using fmemopen() 2941a3b124SEnji Cooper */ 3041a3b124SEnji Cooper 3141a3b124SEnji Cooper #include <errno.h> 3241a3b124SEnji Cooper #include <stdio.h> 3341a3b124SEnji Cooper #include <string.h> 3441a3b124SEnji Cooper #include <strings.h> 351ee02192SEnji Cooper 3641a3b124SEnji Cooper #include <atf-c.h> 3741a3b124SEnji Cooper 3841a3b124SEnji Cooper ATF_TC_WITHOUT_HEAD(test_preexisting); 3941a3b124SEnji Cooper ATF_TC_BODY(test_preexisting, tc) 4041a3b124SEnji Cooper { 411ee02192SEnji Cooper /* Use a pre-existing buffer. */ 4241a3b124SEnji Cooper char buf[512]; 4341a3b124SEnji Cooper char buf2[512]; 4441a3b124SEnji Cooper char str[] = "Test writing some stuff"; 4541a3b124SEnji Cooper char str2[] = "AAAAAAAAA"; 4641a3b124SEnji Cooper char str3[] = "AAAA writing some stuff"; 4741a3b124SEnji Cooper FILE *fp; 4841a3b124SEnji Cooper size_t nofw, nofr; 4941a3b124SEnji Cooper int rc; 5041a3b124SEnji Cooper 5141a3b124SEnji Cooper /* Open a FILE * using fmemopen. */ 5241a3b124SEnji Cooper fp = fmemopen(buf, sizeof(buf), "w"); 5341a3b124SEnji Cooper ATF_REQUIRE(fp != NULL); 5441a3b124SEnji Cooper 5541a3b124SEnji Cooper /* Write to the buffer. */ 5641a3b124SEnji Cooper nofw = fwrite(str, 1, sizeof(str), fp); 5741a3b124SEnji Cooper ATF_REQUIRE(nofw == sizeof(str)); 5841a3b124SEnji Cooper 5941a3b124SEnji Cooper /* Close the FILE *. */ 6041a3b124SEnji Cooper rc = fclose(fp); 6141a3b124SEnji Cooper ATF_REQUIRE(rc == 0); 6241a3b124SEnji Cooper 6341a3b124SEnji Cooper /* Re-open the FILE * to read back the data. */ 6441a3b124SEnji Cooper fp = fmemopen(buf, sizeof(buf), "r"); 6541a3b124SEnji Cooper ATF_REQUIRE(fp != NULL); 6641a3b124SEnji Cooper 6741a3b124SEnji Cooper /* Read from the buffer. */ 6841a3b124SEnji Cooper bzero(buf2, sizeof(buf2)); 6941a3b124SEnji Cooper nofr = fread(buf2, 1, sizeof(buf2), fp); 7041a3b124SEnji Cooper ATF_REQUIRE(nofr == sizeof(buf2)); 7141a3b124SEnji Cooper 7241a3b124SEnji Cooper /* 7341a3b124SEnji Cooper * Since a write on a FILE * retrieved by fmemopen 7441a3b124SEnji Cooper * will add a '\0' (if there's space), we can check 7541a3b124SEnji Cooper * the strings for equality. 7641a3b124SEnji Cooper */ 7741a3b124SEnji Cooper ATF_REQUIRE(strcmp(str, buf2) == 0); 7841a3b124SEnji Cooper 7941a3b124SEnji Cooper /* Close the FILE *. */ 8041a3b124SEnji Cooper rc = fclose(fp); 8141a3b124SEnji Cooper ATF_REQUIRE(rc == 0); 8241a3b124SEnji Cooper 8341a3b124SEnji Cooper /* Now open a FILE * on the first 4 bytes of the string. */ 8441a3b124SEnji Cooper fp = fmemopen(str, 4, "w"); 8541a3b124SEnji Cooper ATF_REQUIRE(fp != NULL); 8641a3b124SEnji Cooper 8741a3b124SEnji Cooper /* 8841a3b124SEnji Cooper * Try to write more bytes than we shoud, we'll get a short count (4). 8941a3b124SEnji Cooper */ 9041a3b124SEnji Cooper nofw = fwrite(str2, 1, sizeof(str2), fp); 9141a3b124SEnji Cooper ATF_REQUIRE(nofw == 4); 9241a3b124SEnji Cooper 9341a3b124SEnji Cooper /* Close the FILE *. */ 9441a3b124SEnji Cooper rc = fclose(fp); 95b95523e8SXin LI ATF_REQUIRE(rc == 0); 9641a3b124SEnji Cooper 9741a3b124SEnji Cooper /* Check that the string was not modified after the first 4 bytes. */ 9841a3b124SEnji Cooper ATF_REQUIRE(strcmp(str, str3) == 0); 9941a3b124SEnji Cooper } 10041a3b124SEnji Cooper 10141a3b124SEnji Cooper ATF_TC_WITHOUT_HEAD(test_autoalloc); 10241a3b124SEnji Cooper ATF_TC_BODY(test_autoalloc, tc) 10341a3b124SEnji Cooper { 1041ee02192SEnji Cooper /* Let fmemopen allocate the buffer. */ 10541a3b124SEnji Cooper FILE *fp; 10641a3b124SEnji Cooper long pos; 10795631a07SBaptiste Daroussin size_t nofw, i; 10841a3b124SEnji Cooper int rc; 10941a3b124SEnji Cooper 11041a3b124SEnji Cooper /* Open a FILE * using fmemopen. */ 11141a3b124SEnji Cooper fp = fmemopen(NULL, 512, "w+"); 11241a3b124SEnji Cooper ATF_REQUIRE(fp != NULL); 11341a3b124SEnji Cooper 11441a3b124SEnji Cooper /* fill the buffer */ 11541a3b124SEnji Cooper for (i = 0; i < 512; i++) { 11641a3b124SEnji Cooper nofw = fwrite("a", 1, 1, fp); 11741a3b124SEnji Cooper ATF_REQUIRE(nofw == 1); 11841a3b124SEnji Cooper } 11941a3b124SEnji Cooper 12041a3b124SEnji Cooper /* Get the current position into the stream. */ 12141a3b124SEnji Cooper pos = ftell(fp); 12241a3b124SEnji Cooper ATF_REQUIRE(pos == 512); 12341a3b124SEnji Cooper 1241ee02192SEnji Cooper /* Try to write past the end, we should get a short object count (0) */ 12541a3b124SEnji Cooper nofw = fwrite("a", 1, 1, fp); 12641a3b124SEnji Cooper ATF_REQUIRE(nofw == 0); 12741a3b124SEnji Cooper 12841a3b124SEnji Cooper /* Close the FILE *. */ 12941a3b124SEnji Cooper rc = fclose(fp); 13041a3b124SEnji Cooper ATF_REQUIRE(rc == 0); 13141a3b124SEnji Cooper 13241a3b124SEnji Cooper /* Open a FILE * using a wrong mode */ 13341a3b124SEnji Cooper fp = fmemopen(NULL, 512, "r"); 13441a3b124SEnji Cooper ATF_REQUIRE(fp == NULL); 135*0953460cSEd Maste ATF_REQUIRE(errno == EINVAL); 13641a3b124SEnji Cooper 13741a3b124SEnji Cooper fp = fmemopen(NULL, 512, "w"); 13841a3b124SEnji Cooper ATF_REQUIRE(fp == NULL); 139*0953460cSEd Maste ATF_REQUIRE(errno == EINVAL); 14041a3b124SEnji Cooper } 14141a3b124SEnji Cooper 14241a3b124SEnji Cooper ATF_TC_WITHOUT_HEAD(test_data_length); 14341a3b124SEnji Cooper ATF_TC_BODY(test_data_length, tc) 14441a3b124SEnji Cooper { 14541a3b124SEnji Cooper /* 14641a3b124SEnji Cooper * Here we test that a read operation doesn't go past the end of the 14741a3b124SEnji Cooper * data actually written, and that a SEEK_END seeks from the end of the 14841a3b124SEnji Cooper * data, not of the whole buffer. 14941a3b124SEnji Cooper */ 15041a3b124SEnji Cooper FILE *fp; 15141a3b124SEnji Cooper char buf[512] = {'\0'}; 15241a3b124SEnji Cooper char str[] = "Test data length. "; 15341a3b124SEnji Cooper char str2[] = "Do we have two sentences?"; 15441a3b124SEnji Cooper char str3[sizeof(str) + sizeof(str2) -1]; 15541a3b124SEnji Cooper long pos; 15641a3b124SEnji Cooper size_t nofw, nofr; 15741a3b124SEnji Cooper int rc; 15841a3b124SEnji Cooper 15941a3b124SEnji Cooper /* Open a FILE * for updating our buffer. */ 16041a3b124SEnji Cooper fp = fmemopen(buf, sizeof(buf), "w+"); 16141a3b124SEnji Cooper ATF_REQUIRE(fp != NULL); 16241a3b124SEnji Cooper 16341a3b124SEnji Cooper /* Write our string into the buffer. */ 16441a3b124SEnji Cooper nofw = fwrite(str, 1, sizeof(str), fp); 16541a3b124SEnji Cooper ATF_REQUIRE(nofw == sizeof(str)); 16641a3b124SEnji Cooper 1671ee02192SEnji Cooper /* Now seek to the end and check that ftell gives us sizeof(str). */ 16841a3b124SEnji Cooper rc = fseek(fp, 0, SEEK_END); 16941a3b124SEnji Cooper ATF_REQUIRE(rc == 0); 17041a3b124SEnji Cooper pos = ftell(fp); 17141a3b124SEnji Cooper ATF_REQUIRE(pos == sizeof(str)); 17241a3b124SEnji Cooper 17341a3b124SEnji Cooper /* Close the FILE *. */ 17441a3b124SEnji Cooper rc = fclose(fp); 17541a3b124SEnji Cooper ATF_REQUIRE(rc == 0); 17641a3b124SEnji Cooper 17741a3b124SEnji Cooper /* Reopen the buffer for appending. */ 17841a3b124SEnji Cooper fp = fmemopen(buf, sizeof(buf), "a+"); 17941a3b124SEnji Cooper ATF_REQUIRE(fp != NULL); 18041a3b124SEnji Cooper 18141a3b124SEnji Cooper /* We should now be writing after the first string. */ 18241a3b124SEnji Cooper nofw = fwrite(str2, 1, sizeof(str2), fp); 18341a3b124SEnji Cooper ATF_REQUIRE(nofw == sizeof(str2)); 18441a3b124SEnji Cooper 18541a3b124SEnji Cooper /* Rewind the FILE *. */ 18641a3b124SEnji Cooper rc = fseek(fp, 0, SEEK_SET); 18741a3b124SEnji Cooper ATF_REQUIRE(rc == 0); 18841a3b124SEnji Cooper 18941a3b124SEnji Cooper /* Make sure we're at the beginning. */ 19041a3b124SEnji Cooper pos = ftell(fp); 19141a3b124SEnji Cooper ATF_REQUIRE(pos == 0); 19241a3b124SEnji Cooper 19341a3b124SEnji Cooper /* Read the whole buffer. */ 19441a3b124SEnji Cooper nofr = fread(str3, 1, sizeof(buf), fp); 19541a3b124SEnji Cooper ATF_REQUIRE(nofr == sizeof(str3)); 19641a3b124SEnji Cooper 19741a3b124SEnji Cooper /* Make sure the two strings are there. */ 19841a3b124SEnji Cooper ATF_REQUIRE(strncmp(str3, str, sizeof(str) - 1) == 0); 19941a3b124SEnji Cooper ATF_REQUIRE(strncmp(str3 + sizeof(str) - 1, str2, sizeof(str2)) == 0); 20041a3b124SEnji Cooper 20141a3b124SEnji Cooper /* Close the FILE *. */ 20241a3b124SEnji Cooper rc = fclose(fp); 20341a3b124SEnji Cooper ATF_REQUIRE(rc == 0); 20441a3b124SEnji Cooper } 20541a3b124SEnji Cooper 20641a3b124SEnji Cooper ATF_TC_WITHOUT_HEAD(test_binary); 20741a3b124SEnji Cooper ATF_TC_BODY(test_binary, tc) 20841a3b124SEnji Cooper { 20941a3b124SEnji Cooper /* 21041a3b124SEnji Cooper * Make sure that NULL bytes are never appended when opening a buffer 21141a3b124SEnji Cooper * in binary mode. 21241a3b124SEnji Cooper */ 21341a3b124SEnji Cooper 21441a3b124SEnji Cooper FILE *fp; 21541a3b124SEnji Cooper char buf[20]; 21641a3b124SEnji Cooper char str[] = "Test"; 21741a3b124SEnji Cooper size_t nofw; 21841a3b124SEnji Cooper int rc, i; 21941a3b124SEnji Cooper 22041a3b124SEnji Cooper /* Pre-fill the buffer. */ 22141a3b124SEnji Cooper memset(buf, 'A', sizeof(buf)); 22241a3b124SEnji Cooper 22341a3b124SEnji Cooper /* Open a FILE * in binary mode. */ 22441a3b124SEnji Cooper fp = fmemopen(buf, sizeof(buf), "w+b"); 22541a3b124SEnji Cooper ATF_REQUIRE(fp != NULL); 22641a3b124SEnji Cooper 22741a3b124SEnji Cooper /* Write some data into it. */ 22841a3b124SEnji Cooper nofw = fwrite(str, 1, strlen(str), fp); 22941a3b124SEnji Cooper ATF_REQUIRE(nofw == strlen(str)); 23041a3b124SEnji Cooper 23141a3b124SEnji Cooper /* Make sure that the buffer doesn't contain any NULL bytes. */ 23241a3b124SEnji Cooper for (i = 0; i < sizeof(buf); i++) 23341a3b124SEnji Cooper ATF_REQUIRE(buf[i] != '\0'); 23441a3b124SEnji Cooper 23541a3b124SEnji Cooper /* Close the FILE *. */ 23641a3b124SEnji Cooper rc = fclose(fp); 23741a3b124SEnji Cooper ATF_REQUIRE(rc == 0); 23841a3b124SEnji Cooper } 23941a3b124SEnji Cooper 24041a3b124SEnji Cooper ATF_TC_WITHOUT_HEAD(test_append_binary_pos); 24141a3b124SEnji Cooper ATF_TC_BODY(test_append_binary_pos, tc) 24241a3b124SEnji Cooper { 24341a3b124SEnji Cooper /* 24441a3b124SEnji Cooper * For compatibility with other implementations (glibc), we set the 24541a3b124SEnji Cooper * position to 0 when opening an automatically allocated binary stream 24641a3b124SEnji Cooper * for appending. 24741a3b124SEnji Cooper */ 24841a3b124SEnji Cooper 24941a3b124SEnji Cooper FILE *fp; 25041a3b124SEnji Cooper 25141a3b124SEnji Cooper fp = fmemopen(NULL, 16, "ab+"); 252c1755e51SEnji Cooper ATF_REQUIRE(fp != NULL); 25341a3b124SEnji Cooper ATF_REQUIRE(ftell(fp) == 0L); 25441a3b124SEnji Cooper fclose(fp); 25541a3b124SEnji Cooper 2561ee02192SEnji Cooper /* Make sure that a pre-allocated buffer behaves correctly. */ 25741a3b124SEnji Cooper char buf[] = "Hello"; 25841a3b124SEnji Cooper fp = fmemopen(buf, sizeof(buf), "ab+"); 259c1755e51SEnji Cooper ATF_REQUIRE(fp != NULL); 26041a3b124SEnji Cooper ATF_REQUIRE(ftell(fp) == strlen(buf)); 26141a3b124SEnji Cooper fclose(fp); 26241a3b124SEnji Cooper } 26341a3b124SEnji Cooper 26441a3b124SEnji Cooper ATF_TC_WITHOUT_HEAD(test_size_0); 26541a3b124SEnji Cooper ATF_TC_BODY(test_size_0, tc) 26641a3b124SEnji Cooper { 2671ee02192SEnji Cooper /* POSIX mandates that we return EINVAL if size is 0. */ 26841a3b124SEnji Cooper 26941a3b124SEnji Cooper FILE *fp; 27041a3b124SEnji Cooper 27141a3b124SEnji Cooper fp = fmemopen(NULL, 0, "r+"); 27241a3b124SEnji Cooper ATF_REQUIRE(fp == NULL); 27341a3b124SEnji Cooper ATF_REQUIRE(errno == EINVAL); 27441a3b124SEnji Cooper } 27541a3b124SEnji Cooper 276*0953460cSEd Maste /* 277*0953460cSEd Maste * PR281953 - ensure we cannot write in read-only only mode, and cannot read in 278*0953460cSEd Maste * write-only mode. 279*0953460cSEd Maste */ 280*0953460cSEd Maste ATF_TC_WITHOUT_HEAD(test_rdonly_wronly); 281*0953460cSEd Maste ATF_TC_BODY(test_rdonly_wronly, tc) 282*0953460cSEd Maste { 283*0953460cSEd Maste FILE *fp; 284*0953460cSEd Maste char buf[16]; 285*0953460cSEd Maste char buf_orig[16] = "input data"; 286*0953460cSEd Maste char buf_write[16] = "write"; 287*0953460cSEd Maste size_t sz; 288*0953460cSEd Maste 289*0953460cSEd Maste memcpy(buf, buf_orig, sizeof(buf)); 290*0953460cSEd Maste fp = fmemopen(buf, sizeof(buf), "r"); 291*0953460cSEd Maste ATF_REQUIRE(fp != NULL); 292*0953460cSEd Maste sz = fwrite(buf_write, 1, strlen(buf_write), fp); 293*0953460cSEd Maste ATF_REQUIRE(sz == 0); 294*0953460cSEd Maste ATF_REQUIRE(errno == EBADF); 295*0953460cSEd Maste ATF_REQUIRE(memcmp(buf, buf_orig, sizeof(buf)) == 0); 296*0953460cSEd Maste fclose(fp); 297*0953460cSEd Maste 298*0953460cSEd Maste fp = fmemopen(buf_orig, sizeof(buf), "w"); 299*0953460cSEd Maste sz = fread(buf, sizeof(buf), 1, fp); 300*0953460cSEd Maste ATF_REQUIRE(sz == 0); 301*0953460cSEd Maste ATF_REQUIRE(errno == EBADF); 302*0953460cSEd Maste fclose(fp); 303*0953460cSEd Maste } 304*0953460cSEd Maste 30541a3b124SEnji Cooper ATF_TP_ADD_TCS(tp) 30641a3b124SEnji Cooper { 30741a3b124SEnji Cooper 30841a3b124SEnji Cooper ATF_TP_ADD_TC(tp, test_autoalloc); 30941a3b124SEnji Cooper ATF_TP_ADD_TC(tp, test_preexisting); 31041a3b124SEnji Cooper ATF_TP_ADD_TC(tp, test_data_length); 31141a3b124SEnji Cooper ATF_TP_ADD_TC(tp, test_binary); 31241a3b124SEnji Cooper ATF_TP_ADD_TC(tp, test_append_binary_pos); 31341a3b124SEnji Cooper ATF_TP_ADD_TC(tp, test_size_0); 314*0953460cSEd Maste ATF_TP_ADD_TC(tp, test_rdonly_wronly); 31541a3b124SEnji Cooper 31641a3b124SEnji Cooper return (atf_no_error()); 31741a3b124SEnji Cooper } 318