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 2009 Sun Microsystems, Inc.  All rights reserved.
  24  */
  25 
  26 #include <stdio.h>
  27 #include <stdlib.h>
  28 #include <unistd.h>
  29 #include <limits.h>
  30 #include <errno.h>
  31 #include <fcntl.h>
  32 #include <sys/types.h>
  33 #include <sys/fcntl.h>
  34 #include <sys/stat.h>
  35 #include <sys/statvfs.h>
  36 #include <sys/errno.h>
  37 #include <sys/time.h>
  38 #include <sys/ioctl.h>
  39 #include <sys/wait.h>
  40 #include <sys/param.h>
  41 #include <string.h>
  42 
  43 #define FSIZE   256*1024*1024
  44 #define BSIZE   512
  45 
  46 /* Initialize Globals */
  47 static long     fsize = FSIZE;
  48 static size_t   bsize = BSIZE;
  49 static int      count = 0;
  50 static int      rflag = 0;
  51 static int      seed = 0;
  52 static int      vflag = 0;
  53 static int      errflag = 0;
  54 static off_t    offset = 0;
  55 static char     *filename = NULL;
  56 
  57 static void usage(char *execname);
  58 static void parse_options(int argc, char *argv[]);
  59 static void do_write(int fd);
  60 static void do_trunc(int fd);
  61 
  62 static void
  63 usage(char *execname)
  64 {
  65         (void) fprintf(stderr,
  66             "usage: %s [-b blocksize] [-c count] [-f filesize]"
  67             " [-o offset] [-s seed] [-r] [-v] filename\n", execname);
  68         (void) exit(1);
  69 }
  70 
  71 int
  72 main(int argc, char *argv[])
  73 {
  74         int i = 0;
  75         int fd = -1;
  76 
  77         parse_options(argc, argv);
  78 
  79         fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0666);
  80         if (fd < 0) {
  81                 perror("open");
  82                 exit(3);
  83         }
  84 
  85         while (i < count) {
  86                 (void) do_write(fd);
  87                 (void) do_trunc(fd);
  88 
  89                 i++;
  90         }
  91 
  92         (void) close(fd);
  93         return (0);
  94 }
  95 
  96 static void
  97 parse_options(int argc, char *argv[])
  98 {
  99         int c;
 100 
 101         extern char *optarg;
 102         extern int optind, optopt;
 103 
 104         count = fsize / bsize;
 105         seed = time(NULL);
 106         while ((c = getopt(argc, argv, "b:c:f:o:rs:v")) != -1) {
 107                 switch (c) {
 108                         case 'b':
 109                                 bsize = atoi(optarg);
 110                                 break;
 111 
 112                         case 'c':
 113                                 count = atoi(optarg);
 114                                 break;
 115 
 116                         case 'f':
 117                                 fsize = atoi(optarg);
 118                                 break;
 119 
 120                         case 'o':
 121                                 offset = atoi(optarg);
 122                                 break;
 123 
 124                         case 'r':
 125                                 rflag++;
 126                                 break;
 127 
 128                         case 's':
 129                                 seed = atoi(optarg);
 130                                 break;
 131 
 132                         case 'v':
 133                                 vflag++;
 134                                 break;
 135 
 136                         case ':':
 137                                 (void) fprintf(stderr,
 138                                     "Option -%c requires an operand\n", optopt);
 139                                 errflag++;
 140                                 break;
 141 
 142                         case '?':
 143                                 (void) fprintf(stderr,
 144                                     "Unrecognized option: -%c\n", optopt);
 145                                 errflag++;
 146                                 break;
 147                 }
 148 
 149                 if (errflag) {
 150                         (void) usage(argv[0]);
 151                 }
 152         }
 153         if (argc <= optind) {
 154                 (void) fprintf(stderr,
 155                     "No filename specified\n");
 156                 usage(argv[0]);
 157         }
 158         filename = argv[optind];
 159 
 160         if (vflag) {
 161                 (void) fprintf(stderr, "Seed = %d\n", seed);
 162         }
 163         srandom(seed);
 164 }
 165 
 166 static void
 167 do_write(int fd)
 168 {
 169         off_t   roffset = 0;
 170         char    *buf = NULL;
 171         char    *rbuf = NULL;
 172 
 173         buf = (char *)calloc(1, bsize);
 174         rbuf = (char *)calloc(1, bsize);
 175         if (buf == NULL || rbuf == NULL) {
 176                 perror("malloc");
 177                 exit(4);
 178         }
 179 
 180         roffset = random() % fsize;
 181         if (lseek64(fd, (offset + roffset), SEEK_SET) < 0) {
 182                 perror("lseek");
 183                 exit(5);
 184         }
 185 
 186         buf = "SMBFS Test Suite Truncation Test";
 187         if (write(fd, buf, bsize) < bsize) {
 188                 perror("write");
 189                 exit(6);
 190         }
 191 
 192         if (rflag) {
 193                 if (lseek64(fd, (offset + roffset), SEEK_SET) < 0) {
 194                         perror("lseek");
 195                         exit(7);
 196                 }
 197 
 198                 if (read(fd, rbuf, bsize) < bsize) {
 199                         perror("read");
 200                         exit(8);
 201                 }
 202 
 203                 if (memcmp(buf, rbuf, bsize) != 0) {
 204                         perror("memcmp");
 205                         exit(9);
 206                 }
 207         }
 208         if (vflag) {
 209                 (void) fprintf(stderr,
 210                     "Wrote to offset %jd\n", (intmax_t)(offset + roffset));
 211                 if (rflag) {
 212                         (void) fprintf(stderr,
 213                             "Read back from offset %jd\n",
 214                             (intmax_t)(offset + roffset));
 215                 }
 216         }
 217 
 218         (void) free(buf);
 219         (void) free(rbuf);
 220 }
 221 
 222 static void
 223 do_trunc(int fd)
 224 {
 225         off_t   roffset = 0;
 226 
 227         roffset = random() % fsize;
 228         if (ftruncate64(fd, (offset + roffset))  < 0) {
 229                 perror("truncate");
 230                 exit(7);
 231         }
 232 
 233         if (vflag) {
 234                 (void) fprintf(stderr,
 235                     "Truncated at offset %jd\n",
 236                     (intmax_t)(offset + roffset));
 237         }
 238 }