1*84d9c625SLionel Sambuc /* $NetBSD: t_io.c,v 1.12 2013/08/04 11:02:02 pooka Exp $ */ 211be35a1SLionel Sambuc 311be35a1SLionel Sambuc /*- 411be35a1SLionel Sambuc * Copyright (c) 2010 The NetBSD Foundation, Inc. 511be35a1SLionel Sambuc * All rights reserved. 611be35a1SLionel Sambuc * 711be35a1SLionel Sambuc * Redistribution and use in source and binary forms, with or without 811be35a1SLionel Sambuc * modification, are permitted provided that the following conditions 911be35a1SLionel Sambuc * are met: 1011be35a1SLionel Sambuc * 1. Redistributions of source code must retain the above copyright 1111be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer. 1211be35a1SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright 1311be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer in the 1411be35a1SLionel Sambuc * documentation and/or other materials provided with the distribution. 1511be35a1SLionel Sambuc * 1611be35a1SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 1711be35a1SLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 1811be35a1SLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1911be35a1SLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2011be35a1SLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2111be35a1SLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2211be35a1SLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2311be35a1SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2411be35a1SLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2511be35a1SLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2611be35a1SLionel Sambuc * POSSIBILITY OF SUCH DAMAGE. 2711be35a1SLionel Sambuc */ 2811be35a1SLionel Sambuc 2911be35a1SLionel Sambuc #include <sys/stat.h> 3011be35a1SLionel Sambuc #include <sys/statvfs.h> 3111be35a1SLionel Sambuc 3211be35a1SLionel Sambuc #include <atf-c.h> 3311be35a1SLionel Sambuc #include <fcntl.h> 3411be35a1SLionel Sambuc #include <libgen.h> 3511be35a1SLionel Sambuc #include <stdlib.h> 3611be35a1SLionel Sambuc #include <unistd.h> 3711be35a1SLionel Sambuc 3811be35a1SLionel Sambuc #include <rump/rump_syscalls.h> 3911be35a1SLionel Sambuc #include <rump/rump.h> 4011be35a1SLionel Sambuc 4111be35a1SLionel Sambuc #include "../common/h_fsmacros.h" 4211be35a1SLionel Sambuc #include "../../h_macros.h" 4311be35a1SLionel Sambuc 4411be35a1SLionel Sambuc #define TESTSTR "this is a string. collect enough and you'll have Em" 4511be35a1SLionel Sambuc #define TESTSZ sizeof(TESTSTR) 4611be35a1SLionel Sambuc 4711be35a1SLionel Sambuc static void 4811be35a1SLionel Sambuc holywrite(const atf_tc_t *tc, const char *mp) 4911be35a1SLionel Sambuc { 5011be35a1SLionel Sambuc char buf[1024]; 5111be35a1SLionel Sambuc char *b2, *b3; 5211be35a1SLionel Sambuc size_t therange = getpagesize()+1; 5311be35a1SLionel Sambuc int fd; 5411be35a1SLionel Sambuc 5511be35a1SLionel Sambuc FSTEST_ENTER(); 5611be35a1SLionel Sambuc 5711be35a1SLionel Sambuc RL(fd = rump_sys_open("file", O_RDWR|O_CREAT|O_TRUNC, 0666)); 5811be35a1SLionel Sambuc 5911be35a1SLionel Sambuc memset(buf, 'A', sizeof(buf)); 6011be35a1SLionel Sambuc RL(rump_sys_pwrite(fd, buf, 1, getpagesize())); 6111be35a1SLionel Sambuc 6211be35a1SLionel Sambuc memset(buf, 'B', sizeof(buf)); 6311be35a1SLionel Sambuc RL(rump_sys_pwrite(fd, buf, 2, getpagesize()-1)); 6411be35a1SLionel Sambuc 6511be35a1SLionel Sambuc REQUIRE_LIBC(b2 = malloc(2 * getpagesize()), NULL); 6611be35a1SLionel Sambuc REQUIRE_LIBC(b3 = malloc(2 * getpagesize()), NULL); 6711be35a1SLionel Sambuc 6811be35a1SLionel Sambuc RL(rump_sys_pread(fd, b2, therange, 0)); 6911be35a1SLionel Sambuc 7011be35a1SLionel Sambuc memset(b3, 0, therange); 7111be35a1SLionel Sambuc memset(b3 + getpagesize() - 1, 'B', 2); 7211be35a1SLionel Sambuc 7311be35a1SLionel Sambuc ATF_REQUIRE_EQ(memcmp(b2, b3, therange), 0); 7411be35a1SLionel Sambuc 7511be35a1SLionel Sambuc rump_sys_close(fd); 7611be35a1SLionel Sambuc FSTEST_EXIT(); 7711be35a1SLionel Sambuc } 7811be35a1SLionel Sambuc 7911be35a1SLionel Sambuc static void 8011be35a1SLionel Sambuc extendbody(const atf_tc_t *tc, off_t seekcnt) 8111be35a1SLionel Sambuc { 8211be35a1SLionel Sambuc char buf[TESTSZ+1]; 8311be35a1SLionel Sambuc struct stat sb; 8411be35a1SLionel Sambuc int fd; 8511be35a1SLionel Sambuc 8611be35a1SLionel Sambuc FSTEST_ENTER(); 8711be35a1SLionel Sambuc RL(fd = rump_sys_open("testfile", 8811be35a1SLionel Sambuc O_CREAT | O_RDWR | (seekcnt ? O_APPEND : 0))); 8911be35a1SLionel Sambuc RL(rump_sys_ftruncate(fd, seekcnt)); 9011be35a1SLionel Sambuc RL(rump_sys_fstat(fd, &sb)); 9111be35a1SLionel Sambuc ATF_REQUIRE_EQ(sb.st_size, seekcnt); 9211be35a1SLionel Sambuc 9311be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_write(fd, TESTSTR, TESTSZ), TESTSZ); 9411be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_pread(fd, buf, TESTSZ, seekcnt), TESTSZ); 9511be35a1SLionel Sambuc ATF_REQUIRE_STREQ(buf, TESTSTR); 9611be35a1SLionel Sambuc 9711be35a1SLionel Sambuc RL(rump_sys_fstat(fd, &sb)); 9811be35a1SLionel Sambuc ATF_REQUIRE_EQ(sb.st_size, (off_t)TESTSZ + seekcnt); 9911be35a1SLionel Sambuc RL(rump_sys_close(fd)); 10011be35a1SLionel Sambuc FSTEST_EXIT(); 10111be35a1SLionel Sambuc } 10211be35a1SLionel Sambuc 10311be35a1SLionel Sambuc static void 10411be35a1SLionel Sambuc extendfile(const atf_tc_t *tc, const char *mp) 10511be35a1SLionel Sambuc { 10611be35a1SLionel Sambuc 10711be35a1SLionel Sambuc extendbody(tc, 0); 10811be35a1SLionel Sambuc } 10911be35a1SLionel Sambuc 11011be35a1SLionel Sambuc static void 11111be35a1SLionel Sambuc extendfile_append(const atf_tc_t *tc, const char *mp) 11211be35a1SLionel Sambuc { 11311be35a1SLionel Sambuc 11411be35a1SLionel Sambuc extendbody(tc, 37); 11511be35a1SLionel Sambuc } 11611be35a1SLionel Sambuc 11711be35a1SLionel Sambuc static void 11811be35a1SLionel Sambuc overwritebody(const atf_tc_t *tc, off_t count, bool dotrunc) 11911be35a1SLionel Sambuc { 12011be35a1SLionel Sambuc char *buf; 12111be35a1SLionel Sambuc int fd; 12211be35a1SLionel Sambuc 12311be35a1SLionel Sambuc REQUIRE_LIBC(buf = malloc(count), NULL); 12411be35a1SLionel Sambuc FSTEST_ENTER(); 12511be35a1SLionel Sambuc RL(fd = rump_sys_open("testi", O_CREAT | O_RDWR, 0666)); 12611be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_write(fd, buf, count), count); 12711be35a1SLionel Sambuc RL(rump_sys_close(fd)); 12811be35a1SLionel Sambuc 12911be35a1SLionel Sambuc RL(fd = rump_sys_open("testi", O_RDWR)); 13011be35a1SLionel Sambuc if (dotrunc) 13111be35a1SLionel Sambuc RL(rump_sys_ftruncate(fd, 0)); 13211be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_write(fd, buf, count), count); 13311be35a1SLionel Sambuc RL(rump_sys_close(fd)); 13411be35a1SLionel Sambuc FSTEST_EXIT(); 13511be35a1SLionel Sambuc } 13611be35a1SLionel Sambuc 13711be35a1SLionel Sambuc static void 13811be35a1SLionel Sambuc overwrite512(const atf_tc_t *tc, const char *mp) 13911be35a1SLionel Sambuc { 14011be35a1SLionel Sambuc 14111be35a1SLionel Sambuc overwritebody(tc, 512, false); 14211be35a1SLionel Sambuc } 14311be35a1SLionel Sambuc 14411be35a1SLionel Sambuc static void 14511be35a1SLionel Sambuc overwrite64k(const atf_tc_t *tc, const char *mp) 14611be35a1SLionel Sambuc { 14711be35a1SLionel Sambuc 14811be35a1SLionel Sambuc overwritebody(tc, 1<<16, false); 14911be35a1SLionel Sambuc } 15011be35a1SLionel Sambuc 15111be35a1SLionel Sambuc static void 15211be35a1SLionel Sambuc overwrite_trunc(const atf_tc_t *tc, const char *mp) 15311be35a1SLionel Sambuc { 15411be35a1SLionel Sambuc 15511be35a1SLionel Sambuc overwritebody(tc, 1<<16, true); 15611be35a1SLionel Sambuc } 15711be35a1SLionel Sambuc 15811be35a1SLionel Sambuc static void 15911be35a1SLionel Sambuc shrinkfile(const atf_tc_t *tc, const char *mp) 16011be35a1SLionel Sambuc { 16111be35a1SLionel Sambuc int fd; 16211be35a1SLionel Sambuc 16311be35a1SLionel Sambuc FSTEST_ENTER(); 16411be35a1SLionel Sambuc RL(fd = rump_sys_open("file", O_RDWR|O_CREAT|O_TRUNC, 0666)); 16511be35a1SLionel Sambuc RL(rump_sys_ftruncate(fd, 2)); 16611be35a1SLionel Sambuc RL(rump_sys_ftruncate(fd, 1)); 16711be35a1SLionel Sambuc rump_sys_close(fd); 16811be35a1SLionel Sambuc FSTEST_EXIT(); 16911be35a1SLionel Sambuc } 17011be35a1SLionel Sambuc 171*84d9c625SLionel Sambuc #define TBSIZE 9000 172*84d9c625SLionel Sambuc static void 173*84d9c625SLionel Sambuc read_after_unlink(const atf_tc_t *tc, const char *mp) 174*84d9c625SLionel Sambuc { 175*84d9c625SLionel Sambuc char buf[TBSIZE], buf2[TBSIZE]; 176*84d9c625SLionel Sambuc int fd; 177*84d9c625SLionel Sambuc 178*84d9c625SLionel Sambuc FSTEST_ENTER(); 179*84d9c625SLionel Sambuc 180*84d9c625SLionel Sambuc /* create file and put some content into it */ 181*84d9c625SLionel Sambuc RL(fd = rump_sys_open("file", O_RDWR|O_CREAT, 0666)); 182*84d9c625SLionel Sambuc memset(buf, 'D', TBSIZE); 183*84d9c625SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_write(fd, buf, TBSIZE), TBSIZE); 184*84d9c625SLionel Sambuc rump_sys_close(fd); 185*84d9c625SLionel Sambuc 186*84d9c625SLionel Sambuc /* flush buffers from UBC to file system */ 187*84d9c625SLionel Sambuc ATF_REQUIRE_ERRNO(EBUSY, rump_sys_unmount(mp, 0) == -1); 188*84d9c625SLionel Sambuc 189*84d9c625SLionel Sambuc RL(fd = rump_sys_open("file", O_RDWR)); 190*84d9c625SLionel Sambuc RL(rump_sys_unlink("file")); 191*84d9c625SLionel Sambuc 192*84d9c625SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_read(fd, buf2, TBSIZE), TBSIZE); 193*84d9c625SLionel Sambuc ATF_REQUIRE_EQ(memcmp(buf, buf2, TBSIZE), 0); 194*84d9c625SLionel Sambuc rump_sys_close(fd); 195*84d9c625SLionel Sambuc 196*84d9c625SLionel Sambuc FSTEST_EXIT(); 197*84d9c625SLionel Sambuc } 198*84d9c625SLionel Sambuc 199*84d9c625SLionel Sambuc static void 200*84d9c625SLionel Sambuc wrrd_after_unlink(const atf_tc_t *tc, const char *mp) 201*84d9c625SLionel Sambuc { 202*84d9c625SLionel Sambuc int value = 0x11; 203*84d9c625SLionel Sambuc int v2; 204*84d9c625SLionel Sambuc int fd; 205*84d9c625SLionel Sambuc 206*84d9c625SLionel Sambuc FSTEST_ENTER(); 207*84d9c625SLionel Sambuc 208*84d9c625SLionel Sambuc RL(fd = rump_sys_open("file", O_RDWR|O_CREAT, 0666)); 209*84d9c625SLionel Sambuc RL(rump_sys_unlink("file")); 210*84d9c625SLionel Sambuc 211*84d9c625SLionel Sambuc RL(rump_sys_pwrite(fd, &value, sizeof(value), 654321)); 212*84d9c625SLionel Sambuc 213*84d9c625SLionel Sambuc /* 214*84d9c625SLionel Sambuc * We can't easily invalidate the buffer since we hold a 215*84d9c625SLionel Sambuc * reference, but try to get them to flush anyway. 216*84d9c625SLionel Sambuc */ 217*84d9c625SLionel Sambuc RL(rump_sys_fsync(fd)); 218*84d9c625SLionel Sambuc RL(rump_sys_pread(fd, &v2, sizeof(v2), 654321)); 219*84d9c625SLionel Sambuc rump_sys_close(fd); 220*84d9c625SLionel Sambuc 221*84d9c625SLionel Sambuc ATF_REQUIRE_EQ(value, v2); 222*84d9c625SLionel Sambuc FSTEST_EXIT(); 223*84d9c625SLionel Sambuc } 224*84d9c625SLionel Sambuc 22511be35a1SLionel Sambuc ATF_TC_FSAPPLY(holywrite, "create a sparse file and fill hole"); 22611be35a1SLionel Sambuc ATF_TC_FSAPPLY(extendfile, "check that extending a file works"); 22711be35a1SLionel Sambuc ATF_TC_FSAPPLY(extendfile_append, "check that extending a file works " 22811be35a1SLionel Sambuc "with a append-only fd (PR kern/44307)"); 22911be35a1SLionel Sambuc ATF_TC_FSAPPLY(overwrite512, "write a 512 byte file twice"); 23011be35a1SLionel Sambuc ATF_TC_FSAPPLY(overwrite64k, "write a 64k byte file twice"); 23111be35a1SLionel Sambuc ATF_TC_FSAPPLY(overwrite_trunc, "write 64k + truncate + rewrite"); 23211be35a1SLionel Sambuc ATF_TC_FSAPPLY(shrinkfile, "shrink file"); 233*84d9c625SLionel Sambuc ATF_TC_FSAPPLY(read_after_unlink, "contents can be read off disk after unlink"); 234*84d9c625SLionel Sambuc ATF_TC_FSAPPLY(wrrd_after_unlink, "file can be written and read after unlink"); 23511be35a1SLionel Sambuc 23611be35a1SLionel Sambuc ATF_TP_ADD_TCS(tp) 23711be35a1SLionel Sambuc { 23811be35a1SLionel Sambuc 23911be35a1SLionel Sambuc ATF_TP_FSAPPLY(holywrite); 24011be35a1SLionel Sambuc ATF_TP_FSAPPLY(extendfile); 24111be35a1SLionel Sambuc ATF_TP_FSAPPLY(extendfile_append); 24211be35a1SLionel Sambuc ATF_TP_FSAPPLY(overwrite512); 24311be35a1SLionel Sambuc ATF_TP_FSAPPLY(overwrite64k); 24411be35a1SLionel Sambuc ATF_TP_FSAPPLY(overwrite_trunc); 24511be35a1SLionel Sambuc ATF_TP_FSAPPLY(shrinkfile); 246*84d9c625SLionel Sambuc ATF_TP_FSAPPLY(read_after_unlink); 247*84d9c625SLionel Sambuc ATF_TP_FSAPPLY(wrrd_after_unlink); 24811be35a1SLionel Sambuc 24911be35a1SLionel Sambuc return atf_no_error(); 25011be35a1SLionel Sambuc } 251