ftruncate_test.c revision 160201
1193323Sed/*- 2193323Sed * Copyright (c) 2006 Robert N. M. Watson 3193323Sed * All rights reserved. 4193323Sed * 5193323Sed * Redistribution and use in source and binary forms, with or without 6193323Sed * modification, are permitted provided that the following conditions 7193323Sed * are met: 8193323Sed * 1. Redistributions of source code must retain the above copyright 9193323Sed * notice, this list of conditions and the following disclaimer. 10193323Sed * 2. Redistributions in binary form must reproduce the above copyright 11193323Sed * notice, this list of conditions and the following disclaimer in the 12193323Sed * documentation and/or other materials provided with the distribution. 13193323Sed * 14193323Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15193323Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17193323Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18193323Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20193323Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24193323Sed * SUCH DAMAGE. 25193323Sed * 26193323Sed * $FreeBSD: head/tools/regression/file/ftruncate/ftruncate.c 160201 2006-07-09 10:56:36Z rwatson $ 27193323Sed */ 28193323Sed 29193323Sed/* 30193323Sed * Very simple regression test. 31193323Sed * 32193323Sed * Future tests that might be of interest: 33193323Sed * 34193323Sed * - Make sure we get EISDIR on a directory. 35193323Sed */ 36193323Sed 37193323Sed#include <sys/types.h> 38193323Sed#include <sys/event.h> 39193323Sed#include <sys/socket.h> 40193323Sed#include <sys/stat.h> 41193323Sed 42193323Sed#include <err.h> 43193323Sed#include <errno.h> 44193323Sed#include <fcntl.h> 45193323Sed#include <inttypes.h> 46193323Sed#include <limits.h> 47193323Sed#include <stdio.h> 48193323Sed#include <unistd.h> 49193323Sed 50193323Sed/* 51193323Sed * Select various potentially interesting lengths at and around power of 2 52193323Sed * edges. 53193323Sed */ 54193323Sedstatic off_t lengths[] = {0, 1, 2, 3, 4, 127, 128, 129, 511, 512, 513, 1023, 55193323Sed 1024, 1025, 2047, 2048, 2049, 4095, 4096, 4097, 8191, 8192, 8193, 16383, 56193323Sed 16384, 16385}; 57193323Sedstatic int lengths_count = sizeof(lengths) / sizeof(off_t); 58193323Sed 59193323Sedint 60193323Sedmain(int argc, char *argv[]) 61193323Sed{ 62193323Sed int error, fd, fds[2], i, read_only_fd; 63193323Sed char path[PATH_MAX]; 64193323Sed struct stat sb; 65193323Sed size_t size; 66193323Sed off_t len; 67193323Sed char ch; 68193323Sed 69193323Sed /* 70193323Sed * Tests using a writable temporary file: grow and then shrink a file 71193323Sed * using ftruncate and various lengths. Make sure that a negative 72193323Sed * file length is rejected. Make sure that when we grow the file, 73193323Sed * bytes now in the range of the file size return 0. 74193323Sed * 75193323Sed * Save a read-only reference to the file to use later for read-only 76193323Sed * descriptor tests. 77193323Sed */ 78193323Sed snprintf(path, PATH_MAX, "/tmp/ftruncate.XXXXXXXXXXXXX"); 79193323Sed fd = mkstemp(path); 80193323Sed if (fd < 0) 81193323Sed err(-1, "makestemp"); 82193323Sed read_only_fd = open(path, O_RDONLY); 83193323Sed if (read_only_fd < 0) { 84193323Sed error = errno; 85193323Sed (void)unlink(path); 86193323Sed errno = error; 87193323Sed err(-1, "open(%s, O_RDONLY)", path); 88193323Sed } 89193323Sed (void)unlink(path); 90193323Sed 91193323Sed if (ftruncate(fd, -1) == 0) 92193323Sed errx(-1, "ftruncate(fd, -1) succeeded"); 93193323Sed if (errno != EINVAL) 94193323Sed err(-1, "ftruncate(fd, -1) returned wrong error"); 95193323Sed 96193323Sed for (i = 0; i < lengths_count; i++) { 97193323Sed len = lengths[i]; 98193323Sed if (ftruncate(fd, len) < 0) 99193323Sed err(-1, "ftruncate(%llu) up", len); 100193323Sed if (fstat(fd, &sb) < 0) 101193323Sed err(-1, "stat"); 102193323Sed if (sb.st_size != len) 103193323Sed errx(-1, "fstat(%llu) returned len %llu up", len, 104193323Sed sb.st_size); 105193323Sed if (len != 0) { 106193323Sed size = pread(fd, &ch, sizeof(ch), len - 1); 107193323Sed if (size < 0) 108193323Sed err(-1, "pread on len %llu up", len); 109193323Sed if (size != sizeof(ch)) 110193323Sed errx(-1, "pread len %llu size %jd up", 111193323Sed len, (intmax_t)size); 112193323Sed if (ch != 0) 113193323Sed errx(-1, 114193323Sed "pread length %llu size %jd ch %d up", 115193323Sed len, (intmax_t)size, ch); 116193323Sed } 117193323Sed } 118193323Sed 119193323Sed for (i = lengths_count - 1; i >= 0; i--) { 120193323Sed len = lengths[i]; 121193323Sed if (ftruncate(fd, len) < 0) 122193323Sed err(-1, "ftruncate(%llu) down", len); 123193323Sed if (fstat(fd, &sb) < 0) 124193323Sed err(-1, "stat"); 125193323Sed if (sb.st_size != len) 126193323Sed errx(-1, "fstat(%llu) returned %llu down", len, 127193323Sed sb.st_size); 128193323Sed } 129193323Sed close(fd); 130193323Sed 131193323Sed /* 132193323Sed * Make sure that a read-only descriptor can't be truncated. 133193323Sed */ 134193323Sed if (ftruncate(read_only_fd, 0) == 0) 135193323Sed errx(-1, "ftruncate(read_only_fd) succeeded"); 136193323Sed if (errno != EINVAL) 137193323Sed err(-1, "ftruncate(read_only_fd) returned wrong error"); 138193323Sed close(read_only_fd); 139193323Sed 140193323Sed /* 141193323Sed * Make sure that ftruncate on sockets doesn't work. 142193323Sed */ 143193323Sed fd = socket(PF_UNIX, SOCK_STREAM, 0); 144193323Sed if (fd < 0) 145193323Sed err(-1, "socket(PF_UNIX, SOCK_STREAM, 0)"); 146193323Sed if (ftruncate(fd, 0) == 0) 147193323Sed errx(-1, "ftruncate(socket) succeeded"); 148 if (errno != EINVAL) 149 err(-1, "ftruncate(socket) returned wrong error"); 150 close(fd); 151 152 /* 153 * Make sure that ftruncate on pipes doesn't work. 154 */ 155 if (pipe(fds) < 0) 156 err(-1, "pipe"); 157 if (ftruncate(fds[0], 0) == 0) 158 errx(-1, "ftruncate(pipe) succeeded"); 159 if (errno != EINVAL) 160 err(-1, "ftruncate(pipe) returned wrong error"); 161 close(fds[0]); 162 close(fds[1]); 163 164 /* 165 * Make sure that ftruncate on kqueues doesn't work. 166 */ 167 fd = kqueue(); 168 if (fd < 0) 169 err(-1, "kqueue"); 170 if (ftruncate(fds[0], 0) == 0) 171 errx(-1, "ftruncate(kqueue) succeeded"); 172 if (errno != EINVAL) 173 err(-1, "ftruncate(kqueue) returned wrong error"); 174 close(fd); 175 176 return (0); 177} 178