1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "@(#)file_trunc.c 1.2 07/05/25 SMI" 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <unistd.h> 31 #include <limits.h> 32 #include <errno.h> 33 #include <fcntl.h> 34 #include <sys/types.h> 35 #include <sys/fcntl.h> 36 #include <sys/stat.h> 37 #include <sys/statvfs.h> 38 #include <sys/errno.h> 39 #include <sys/time.h> 40 #include <sys/ioctl.h> 41 #include <sys/wait.h> 42 #include <sys/param.h> 43 #include <string.h> 44 45 #define FSIZE 256*1024*1024 46 #define BSIZE 512 47 48 /* Initialize Globals */ 49 static long fsize = FSIZE; 50 static size_t bsize = BSIZE; 51 static int count = 0; 52 static int rflag = 0; 53 static int seed = 0; 54 static int vflag = 0; 55 static int errflag = 0; 56 static off_t offset = 0; 57 static char *filename = NULL; 58 59 static void usage(char *execname); 60 static void parse_options(int argc, char *argv[]); 61 static void do_write(int fd); 62 static void do_trunc(int fd); 63 64 static void 65 usage(char *execname) 66 { 67 (void) fprintf(stderr, 68 "usage: %s [-b blocksize] [-c count] [-f filesize]" 69 " [-o offset] [-s seed] [-r] [-v] filename\n", execname); 70 (void) exit(1); 71 } 72 73 int 74 main(int argc, char *argv[]) 75 { 76 int i = 0; 77 int fd = -1; 78 79 parse_options(argc, argv); 80 81 fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0666); 82 if (fd < 0) { 83 perror("open"); 84 exit(3); 85 } 86 87 while (i < count) { 88 (void) do_write(fd); 89 (void) do_trunc(fd); 90 91 i++; 92 } 93 94 (void) close(fd); 95 return (0); 96 } 97 98 static void 99 parse_options(int argc, char *argv[]) 100 { 101 int c; 102 103 extern char *optarg; 104 extern int optind, optopt; 105 106 count = fsize / bsize; 107 seed = time(NULL); 108 while ((c = getopt(argc, argv, "b:c:f:o:rs:v")) != -1) { 109 switch (c) { 110 case 'b': 111 bsize = atoi(optarg); 112 break; 113 114 case 'c': 115 count = atoi(optarg); 116 break; 117 118 case 'f': 119 fsize = atoi(optarg); 120 break; 121 122 case 'o': 123 offset = atoi(optarg); 124 break; 125 126 case 'r': 127 rflag++; 128 break; 129 130 case 's': 131 seed = atoi(optarg); 132 break; 133 134 case 'v': 135 vflag++; 136 break; 137 138 case ':': 139 (void) fprintf(stderr, 140 "Option -%c requires an operand\n", optopt); 141 errflag++; 142 break; 143 144 case '?': 145 (void) fprintf(stderr, 146 "Unrecognized option: -%c\n", optopt); 147 errflag++; 148 break; 149 } 150 151 if (errflag) { 152 (void) usage(argv[0]); 153 } 154 } 155 if (argc <= optind) { 156 (void) fprintf(stderr, 157 "No filename specified\n"); 158 usage(argv[0]); 159 } 160 filename = argv[optind]; 161 162 if (vflag) { 163 (void) fprintf(stderr, "Seed = %d\n", seed); 164 } 165 srandom(seed); 166 } 167 168 static void 169 do_write(int fd) 170 { 171 off_t roffset = 0; 172 char *buf = NULL; 173 char *rbuf = NULL; 174 175 buf = (char *)calloc(1, bsize); 176 rbuf = (char *)calloc(1, bsize); 177 if (buf == NULL || rbuf == NULL) { 178 perror("malloc"); 179 exit(4); 180 } 181 182 roffset = random() % fsize; 183 if (lseek(fd, (offset + roffset), SEEK_SET) < 0) { 184 perror("lseek"); 185 exit(5); 186 } 187 188 strcpy(buf, "ZFS Test Suite Truncation Test"); 189 if (write(fd, buf, bsize) < bsize) { 190 perror("write"); 191 exit(6); 192 } 193 194 if (rflag) { 195 if (lseek(fd, (offset + roffset), SEEK_SET) < 0) { 196 perror("lseek"); 197 exit(7); 198 } 199 200 if (read(fd, rbuf, bsize) < bsize) { 201 perror("read"); 202 exit(8); 203 } 204 205 if (memcmp(buf, rbuf, bsize) != 0) { 206 perror("memcmp"); 207 exit(9); 208 } 209 } 210 if (vflag) { 211 (void) fprintf(stderr, 212 "Wrote to offset %ld\n", (offset + roffset)); 213 if (rflag) { 214 (void) fprintf(stderr, 215 "Read back from offset %ld\n", (offset + roffset)); 216 } 217 } 218 219 (void) free(buf); 220 (void) free(rbuf); 221 } 222 223 static void 224 do_trunc(int fd) 225 { 226 off_t roffset = 0; 227 228 roffset = random() % fsize; 229 if (ftruncate(fd, (offset + roffset)) < 0) { 230 perror("truncate"); 231 exit(7); 232 } 233 234 if (vflag) { 235 (void) fprintf(stderr, 236 "Truncated at offset %ld\n", 237 (offset + roffset)); 238 } 239 } 240