1314818Sngie/* $NetBSD: t_io.c,v 1.17 2017/01/13 21:30:40 christos Exp $ */ 2272343Sngie 3272343Sngie/*- 4272343Sngie * Copyright (c) 2010 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * Redistribution and use in source and binary forms, with or without 8272343Sngie * modification, are permitted provided that the following conditions 9272343Sngie * are met: 10272343Sngie * 1. Redistributions of source code must retain the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer. 12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 13272343Sngie * notice, this list of conditions and the following disclaimer in the 14272343Sngie * documentation and/or other materials provided with the distribution. 15272343Sngie * 16272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26272343Sngie * POSSIBILITY OF SUCH DAMAGE. 27272343Sngie */ 28272343Sngie 29272343Sngie#include <sys/stat.h> 30272343Sngie#include <sys/statvfs.h> 31272343Sngie 32272343Sngie#include <atf-c.h> 33272343Sngie#include <fcntl.h> 34272343Sngie#include <libgen.h> 35272343Sngie#include <stdlib.h> 36272343Sngie#include <unistd.h> 37272343Sngie 38272343Sngie#include <rump/rump_syscalls.h> 39272343Sngie#include <rump/rump.h> 40272343Sngie 41272343Sngie#include "../common/h_fsmacros.h" 42314818Sngie#include "h_macros.h" 43272343Sngie 44272343Sngie#define TESTSTR "this is a string. collect enough and you'll have Em" 45272343Sngie#define TESTSZ sizeof(TESTSTR) 46272343Sngie 47272343Sngiestatic void 48272343Sngieholywrite(const atf_tc_t *tc, const char *mp) 49272343Sngie{ 50272343Sngie char buf[1024]; 51272343Sngie char *b2, *b3; 52272343Sngie size_t therange = getpagesize()+1; 53272343Sngie int fd; 54272343Sngie 55272343Sngie FSTEST_ENTER(); 56272343Sngie 57272343Sngie RL(fd = rump_sys_open("file", O_RDWR|O_CREAT|O_TRUNC, 0666)); 58272343Sngie 59272343Sngie memset(buf, 'A', sizeof(buf)); 60272343Sngie RL(rump_sys_pwrite(fd, buf, 1, getpagesize())); 61272343Sngie 62272343Sngie memset(buf, 'B', sizeof(buf)); 63272343Sngie RL(rump_sys_pwrite(fd, buf, 2, getpagesize()-1)); 64272343Sngie 65272343Sngie REQUIRE_LIBC(b2 = malloc(2 * getpagesize()), NULL); 66272343Sngie REQUIRE_LIBC(b3 = malloc(2 * getpagesize()), NULL); 67272343Sngie 68272343Sngie RL(rump_sys_pread(fd, b2, therange, 0)); 69272343Sngie 70272343Sngie memset(b3, 0, therange); 71272343Sngie memset(b3 + getpagesize() - 1, 'B', 2); 72272343Sngie 73272343Sngie ATF_REQUIRE_EQ(memcmp(b2, b3, therange), 0); 74272343Sngie 75272343Sngie rump_sys_close(fd); 76272343Sngie FSTEST_EXIT(); 77272343Sngie} 78272343Sngie 79272343Sngiestatic void 80272343Sngieextendbody(const atf_tc_t *tc, off_t seekcnt) 81272343Sngie{ 82272343Sngie char buf[TESTSZ+1]; 83272343Sngie struct stat sb; 84272343Sngie int fd; 85272343Sngie 86272343Sngie FSTEST_ENTER(); 87272343Sngie RL(fd = rump_sys_open("testfile", 88272343Sngie O_CREAT | O_RDWR | (seekcnt ? O_APPEND : 0))); 89272343Sngie RL(rump_sys_ftruncate(fd, seekcnt)); 90272343Sngie RL(rump_sys_fstat(fd, &sb)); 91272343Sngie ATF_REQUIRE_EQ(sb.st_size, seekcnt); 92272343Sngie 93272343Sngie ATF_REQUIRE_EQ(rump_sys_write(fd, TESTSTR, TESTSZ), TESTSZ); 94272343Sngie ATF_REQUIRE_EQ(rump_sys_pread(fd, buf, TESTSZ, seekcnt), TESTSZ); 95272343Sngie ATF_REQUIRE_STREQ(buf, TESTSTR); 96272343Sngie 97272343Sngie RL(rump_sys_fstat(fd, &sb)); 98272343Sngie ATF_REQUIRE_EQ(sb.st_size, (off_t)TESTSZ + seekcnt); 99272343Sngie RL(rump_sys_close(fd)); 100272343Sngie FSTEST_EXIT(); 101272343Sngie} 102272343Sngie 103272343Sngiestatic void 104272343Sngieextendfile(const atf_tc_t *tc, const char *mp) 105272343Sngie{ 106272343Sngie 107272343Sngie extendbody(tc, 0); 108272343Sngie} 109272343Sngie 110272343Sngiestatic void 111272343Sngieextendfile_append(const atf_tc_t *tc, const char *mp) 112272343Sngie{ 113272343Sngie 114272343Sngie extendbody(tc, 37); 115272343Sngie} 116272343Sngie 117272343Sngiestatic void 118272343Sngieoverwritebody(const atf_tc_t *tc, off_t count, bool dotrunc) 119272343Sngie{ 120272343Sngie char *buf; 121272343Sngie int fd; 122272343Sngie 123272343Sngie REQUIRE_LIBC(buf = malloc(count), NULL); 124272343Sngie FSTEST_ENTER(); 125272343Sngie RL(fd = rump_sys_open("testi", O_CREAT | O_RDWR, 0666)); 126272343Sngie ATF_REQUIRE_EQ(rump_sys_write(fd, buf, count), count); 127272343Sngie RL(rump_sys_close(fd)); 128272343Sngie 129272343Sngie RL(fd = rump_sys_open("testi", O_RDWR)); 130272343Sngie if (dotrunc) 131272343Sngie RL(rump_sys_ftruncate(fd, 0)); 132272343Sngie ATF_REQUIRE_EQ(rump_sys_write(fd, buf, count), count); 133272343Sngie RL(rump_sys_close(fd)); 134272343Sngie FSTEST_EXIT(); 135272343Sngie} 136272343Sngie 137272343Sngiestatic void 138272343Sngieoverwrite512(const atf_tc_t *tc, const char *mp) 139272343Sngie{ 140272343Sngie 141272343Sngie overwritebody(tc, 512, false); 142272343Sngie} 143272343Sngie 144272343Sngiestatic void 145272343Sngieoverwrite64k(const atf_tc_t *tc, const char *mp) 146272343Sngie{ 147272343Sngie 148272343Sngie overwritebody(tc, 1<<16, false); 149272343Sngie} 150272343Sngie 151272343Sngiestatic void 152272343Sngieoverwrite_trunc(const atf_tc_t *tc, const char *mp) 153272343Sngie{ 154272343Sngie 155272343Sngie overwritebody(tc, 1<<16, true); 156272343Sngie} 157272343Sngie 158272343Sngiestatic void 159272343Sngieshrinkfile(const atf_tc_t *tc, const char *mp) 160272343Sngie{ 161272343Sngie int fd; 162272343Sngie 163272343Sngie FSTEST_ENTER(); 164272343Sngie RL(fd = rump_sys_open("file", O_RDWR|O_CREAT|O_TRUNC, 0666)); 165272343Sngie RL(rump_sys_ftruncate(fd, 2)); 166272343Sngie RL(rump_sys_ftruncate(fd, 1)); 167272343Sngie rump_sys_close(fd); 168272343Sngie FSTEST_EXIT(); 169272343Sngie} 170272343Sngie 171272343Sngie#define TBSIZE 9000 172272343Sngiestatic void 173272343Sngieread_after_unlink(const atf_tc_t *tc, const char *mp) 174272343Sngie{ 175272343Sngie char buf[TBSIZE], buf2[TBSIZE]; 176272343Sngie int fd; 177272343Sngie 178272343Sngie FSTEST_ENTER(); 179272343Sngie 180272343Sngie /* create file and put some content into it */ 181272343Sngie RL(fd = rump_sys_open("file", O_RDWR|O_CREAT, 0666)); 182272343Sngie memset(buf, 'D', TBSIZE); 183272343Sngie ATF_REQUIRE_EQ(rump_sys_write(fd, buf, TBSIZE), TBSIZE); 184272343Sngie rump_sys_close(fd); 185272343Sngie 186272343Sngie /* flush buffers from UBC to file system */ 187272343Sngie ATF_REQUIRE_ERRNO(EBUSY, rump_sys_unmount(mp, 0) == -1); 188272343Sngie 189272343Sngie RL(fd = rump_sys_open("file", O_RDWR)); 190272343Sngie RL(rump_sys_unlink("file")); 191272343Sngie 192272343Sngie ATF_REQUIRE_EQ(rump_sys_read(fd, buf2, TBSIZE), TBSIZE); 193272343Sngie ATF_REQUIRE_EQ(memcmp(buf, buf2, TBSIZE), 0); 194272343Sngie rump_sys_close(fd); 195272343Sngie 196272343Sngie FSTEST_EXIT(); 197272343Sngie} 198272343Sngie 199272343Sngiestatic void 200272343Sngiewrrd_after_unlink(const atf_tc_t *tc, const char *mp) 201272343Sngie{ 202272343Sngie int value = 0x11; 203272343Sngie int v2; 204272343Sngie int fd; 205272343Sngie 206272343Sngie FSTEST_ENTER(); 207272343Sngie 208272343Sngie RL(fd = rump_sys_open("file", O_RDWR|O_CREAT, 0666)); 209272343Sngie RL(rump_sys_unlink("file")); 210272343Sngie 211272343Sngie RL(rump_sys_pwrite(fd, &value, sizeof(value), 654321)); 212272343Sngie 213272343Sngie /* 214272343Sngie * We can't easily invalidate the buffer since we hold a 215272343Sngie * reference, but try to get them to flush anyway. 216272343Sngie */ 217272343Sngie RL(rump_sys_fsync(fd)); 218272343Sngie RL(rump_sys_pread(fd, &v2, sizeof(v2), 654321)); 219272343Sngie rump_sys_close(fd); 220272343Sngie 221272343Sngie ATF_REQUIRE_EQ(value, v2); 222272343Sngie FSTEST_EXIT(); 223272343Sngie} 224272343Sngie 225309466Sngiestatic void 226309466Sngieread_fault(const atf_tc_t *tc, const char *mp) 227309466Sngie{ 228309466Sngie char ch = 123; 229309466Sngie int fd; 230309466Sngie 231309466Sngie FSTEST_ENTER(); 232309466Sngie RL(fd = rump_sys_open("file", O_CREAT | O_RDWR, 0777)); 233309466Sngie ATF_REQUIRE_EQ(rump_sys_write(fd, &ch, 1), 1); 234309466Sngie RL(rump_sys_close(fd)); 235309466Sngie RL(fd = rump_sys_open("file", O_RDONLY | O_SYNC | O_RSYNC)); 236309466Sngie ATF_REQUIRE_ERRNO(EFAULT, rump_sys_read(fd, NULL, 1) == -1); 237309466Sngie RL(rump_sys_close(fd)); 238309466Sngie FSTEST_EXIT(); 239309466Sngie} 240309466Sngie 241272343SngieATF_TC_FSAPPLY(holywrite, "create a sparse file and fill hole"); 242272343SngieATF_TC_FSAPPLY(extendfile, "check that extending a file works"); 243272343SngieATF_TC_FSAPPLY(extendfile_append, "check that extending a file works " 244272343Sngie "with a append-only fd (PR kern/44307)"); 245272343SngieATF_TC_FSAPPLY(overwrite512, "write a 512 byte file twice"); 246272343SngieATF_TC_FSAPPLY(overwrite64k, "write a 64k byte file twice"); 247272343SngieATF_TC_FSAPPLY(overwrite_trunc, "write 64k + truncate + rewrite"); 248272343SngieATF_TC_FSAPPLY(shrinkfile, "shrink file"); 249272343SngieATF_TC_FSAPPLY(read_after_unlink, "contents can be read off disk after unlink"); 250272343SngieATF_TC_FSAPPLY(wrrd_after_unlink, "file can be written and read after unlink"); 251309466SngieATF_TC_FSAPPLY(read_fault, "read at bad address must return EFAULT"); 252272343Sngie 253272343SngieATF_TP_ADD_TCS(tp) 254272343Sngie{ 255272343Sngie 256272343Sngie ATF_TP_FSAPPLY(holywrite); 257272343Sngie ATF_TP_FSAPPLY(extendfile); 258272343Sngie ATF_TP_FSAPPLY(extendfile_append); 259272343Sngie ATF_TP_FSAPPLY(overwrite512); 260272343Sngie ATF_TP_FSAPPLY(overwrite64k); 261272343Sngie ATF_TP_FSAPPLY(overwrite_trunc); 262272343Sngie ATF_TP_FSAPPLY(shrinkfile); 263272343Sngie ATF_TP_FSAPPLY(read_after_unlink); 264272343Sngie ATF_TP_FSAPPLY(wrrd_after_unlink); 265309466Sngie ATF_TP_FSAPPLY(read_fault); 266272343Sngie 267272343Sngie return atf_no_error(); 268272343Sngie} 269