196c8483Yuri Pankov/*
296c8483Yuri Pankov * CDDL HEADER START
396c8483Yuri Pankov *
496c8483Yuri Pankov * The contents of this file are subject to the terms of the
596c8483Yuri Pankov * Common Development and Distribution License (the "License").
696c8483Yuri Pankov * You may not use this file except in compliance with the License.
796c8483Yuri Pankov *
896c8483Yuri Pankov * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
996c8483Yuri Pankov * or http://www.opensolaris.org/os/licensing.
1096c8483Yuri Pankov * See the License for the specific language governing permissions
1196c8483Yuri Pankov * and limitations under the License.
1296c8483Yuri Pankov *
1396c8483Yuri Pankov * When distributing Covered Code, include this CDDL HEADER in each
1496c8483Yuri Pankov * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1596c8483Yuri Pankov * If applicable, add the following below this CDDL HEADER, with the
1696c8483Yuri Pankov * fields enclosed by brackets "[]" replaced with your own identifying
1796c8483Yuri Pankov * information: Portions Copyright [yyyy] [name of copyright owner]
1896c8483Yuri Pankov *
1996c8483Yuri Pankov * CDDL HEADER END
2096c8483Yuri Pankov */
2196c8483Yuri Pankov
2296c8483Yuri Pankov/*
2396c8483Yuri Pankov * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2496c8483Yuri Pankov */
2596c8483Yuri Pankov
2696c8483Yuri Pankov#include <stdio.h>
2796c8483Yuri Pankov#include <stdlib.h>
2896c8483Yuri Pankov#include <unistd.h>
2996c8483Yuri Pankov#include <limits.h>
3096c8483Yuri Pankov#include <errno.h>
3196c8483Yuri Pankov#include <fcntl.h>
3296c8483Yuri Pankov#include <sys/types.h>
3396c8483Yuri Pankov#include <sys/fcntl.h>
3496c8483Yuri Pankov#include <sys/stat.h>
3596c8483Yuri Pankov#include <sys/statvfs.h>
3696c8483Yuri Pankov#include <sys/errno.h>
3796c8483Yuri Pankov#include <sys/time.h>
3896c8483Yuri Pankov#include <sys/ioctl.h>
3996c8483Yuri Pankov#include <sys/wait.h>
4096c8483Yuri Pankov#include <sys/param.h>
4196c8483Yuri Pankov#include <string.h>
4296c8483Yuri Pankov
4396c8483Yuri Pankov#define	FSIZE	256*1024*1024
4496c8483Yuri Pankov#define	BSIZE	512
4596c8483Yuri Pankov
4696c8483Yuri Pankov/* Initialize Globals */
4796c8483Yuri Pankovstatic long	fsize = FSIZE;
4896c8483Yuri Pankovstatic size_t	bsize = BSIZE;
4996c8483Yuri Pankovstatic int	count = 0;
5096c8483Yuri Pankovstatic int	rflag = 0;
5196c8483Yuri Pankovstatic int	seed = 0;
5296c8483Yuri Pankovstatic int	vflag = 0;
5396c8483Yuri Pankovstatic int	errflag = 0;
5496c8483Yuri Pankovstatic off_t	offset = 0;
5596c8483Yuri Pankovstatic char	*filename = NULL;
5696c8483Yuri Pankov
5796c8483Yuri Pankovstatic void usage(char *execname);
5896c8483Yuri Pankovstatic void parse_options(int argc, char *argv[]);
5996c8483Yuri Pankovstatic void do_write(int fd);
6096c8483Yuri Pankovstatic void do_trunc(int fd);
6196c8483Yuri Pankov
6296c8483Yuri Pankovstatic void
6396c8483Yuri Pankovusage(char *execname)
6496c8483Yuri Pankov{
6596c8483Yuri Pankov	(void) fprintf(stderr,
6696c8483Yuri Pankov	    "usage: %s [-b blocksize] [-c count] [-f filesize]"
6796c8483Yuri Pankov	    " [-o offset] [-s seed] [-r] [-v] filename\n", execname);
6896c8483Yuri Pankov	(void) exit(1);
6996c8483Yuri Pankov}
7096c8483Yuri Pankov
7196c8483Yuri Pankovint
7296c8483Yuri Pankovmain(int argc, char *argv[])
7396c8483Yuri Pankov{
7496c8483Yuri Pankov	int i = 0;
7596c8483Yuri Pankov	int fd = -1;
7696c8483Yuri Pankov
7796c8483Yuri Pankov	parse_options(argc, argv);
7896c8483Yuri Pankov
7996c8483Yuri Pankov	fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0666);
8096c8483Yuri Pankov	if (fd < 0) {
8196c8483Yuri Pankov		perror("open");
8296c8483Yuri Pankov		exit(3);
8396c8483Yuri Pankov	}
8496c8483Yuri Pankov
8596c8483Yuri Pankov	while (i < count) {
8696c8483Yuri Pankov		(void) do_write(fd);
8796c8483Yuri Pankov		(void) do_trunc(fd);
8896c8483Yuri Pankov
8996c8483Yuri Pankov		i++;
9096c8483Yuri Pankov	}
9196c8483Yuri Pankov
9296c8483Yuri Pankov	(void) close(fd);
9396c8483Yuri Pankov	return (0);
9496c8483Yuri Pankov}
9596c8483Yuri Pankov
9696c8483Yuri Pankovstatic void
9796c8483Yuri Pankovparse_options(int argc, char *argv[])
9896c8483Yuri Pankov{
9996c8483Yuri Pankov	int c;
10096c8483Yuri Pankov
10196c8483Yuri Pankov	extern char *optarg;
10296c8483Yuri Pankov	extern int optind, optopt;
10396c8483Yuri Pankov
10496c8483Yuri Pankov	count = fsize / bsize;
10596c8483Yuri Pankov	seed = time(NULL);
10696c8483Yuri Pankov	while ((c = getopt(argc, argv, "b:c:f:o:rs:v")) != -1) {
10796c8483Yuri Pankov		switch (c) {
10896c8483Yuri Pankov			case 'b':
10996c8483Yuri Pankov				bsize = atoi(optarg);
11096c8483Yuri Pankov				break;
11196c8483Yuri Pankov
11296c8483Yuri Pankov			case 'c':
11396c8483Yuri Pankov				count = atoi(optarg);
11496c8483Yuri Pankov				break;
11596c8483Yuri Pankov
11696c8483Yuri Pankov			case 'f':
11796c8483Yuri Pankov				fsize = atoi(optarg);
11896c8483Yuri Pankov				break;
11996c8483Yuri Pankov
12096c8483Yuri Pankov			case 'o':
12196c8483Yuri Pankov				offset = atoi(optarg);
12296c8483Yuri Pankov				break;
12396c8483Yuri Pankov
12496c8483Yuri Pankov			case 'r':
12596c8483Yuri Pankov				rflag++;
12696c8483Yuri Pankov				break;
12796c8483Yuri Pankov
12896c8483Yuri Pankov			case 's':
12996c8483Yuri Pankov				seed = atoi(optarg);
13096c8483Yuri Pankov				break;
13196c8483Yuri Pankov
13296c8483Yuri Pankov			case 'v':
13396c8483Yuri Pankov				vflag++;
13496c8483Yuri Pankov				break;
13596c8483Yuri Pankov
13696c8483Yuri Pankov			case ':':
13796c8483Yuri Pankov				(void) fprintf(stderr,
13896c8483Yuri Pankov				    "Option -%c requires an operand\n", optopt);
13996c8483Yuri Pankov				errflag++;
14096c8483Yuri Pankov				break;
14196c8483Yuri Pankov
14296c8483Yuri Pankov			case '?':
14396c8483Yuri Pankov				(void) fprintf(stderr,
14496c8483Yuri Pankov				    "Unrecognized option: -%c\n", optopt);
14596c8483Yuri Pankov				errflag++;
14696c8483Yuri Pankov				break;
14796c8483Yuri Pankov		}
14896c8483Yuri Pankov
14996c8483Yuri Pankov		if (errflag) {
15096c8483Yuri Pankov			(void) usage(argv[0]);
15196c8483Yuri Pankov		}
15296c8483Yuri Pankov	}
15396c8483Yuri Pankov	if (argc <= optind) {
15496c8483Yuri Pankov		(void) fprintf(stderr,
15596c8483Yuri Pankov		    "No filename specified\n");
15696c8483Yuri Pankov		usage(argv[0]);
15796c8483Yuri Pankov	}
15896c8483Yuri Pankov	filename = argv[optind];
15996c8483Yuri Pankov
16096c8483Yuri Pankov	if (vflag) {
16196c8483Yuri Pankov		(void) fprintf(stderr, "Seed = %d\n", seed);
16296c8483Yuri Pankov	}
16396c8483Yuri Pankov	srandom(seed);
16496c8483Yuri Pankov}
16596c8483Yuri Pankov
16696c8483Yuri Pankovstatic void
16796c8483Yuri Pankovdo_write(int fd)
16896c8483Yuri Pankov{
16996c8483Yuri Pankov	off_t	roffset = 0;
17096c8483Yuri Pankov	char	*buf = NULL;
17196c8483Yuri Pankov	char	*rbuf = NULL;
17296c8483Yuri Pankov
17396c8483Yuri Pankov	buf = (char *)calloc(1, bsize);
17496c8483Yuri Pankov	rbuf = (char *)calloc(1, bsize);
17596c8483Yuri Pankov	if (buf == NULL || rbuf == NULL) {
17696c8483Yuri Pankov		perror("malloc");
17796c8483Yuri Pankov		exit(4);
17896c8483Yuri Pankov	}
17996c8483Yuri Pankov
18096c8483Yuri Pankov	roffset = random() % fsize;
18196c8483Yuri Pankov	if (lseek64(fd, (offset + roffset), SEEK_SET) < 0) {
18296c8483Yuri Pankov		perror("lseek");
18396c8483Yuri Pankov		exit(5);
18496c8483Yuri Pankov	}
18596c8483Yuri Pankov
18696c8483Yuri Pankov	buf = "SMBFS Test Suite Truncation Test";
18796c8483Yuri Pankov	if (write(fd, buf, bsize) < bsize) {
18896c8483Yuri Pankov		perror("write");
18996c8483Yuri Pankov		exit(6);
19096c8483Yuri Pankov	}
19196c8483Yuri Pankov
19296c8483Yuri Pankov	if (rflag) {
19396c8483Yuri Pankov		if (lseek64(fd, (offset + roffset), SEEK_SET) < 0) {
19496c8483Yuri Pankov			perror("lseek");
19596c8483Yuri Pankov			exit(7);
19696c8483Yuri Pankov		}
19796c8483Yuri Pankov
19896c8483Yuri Pankov		if (read(fd, rbuf, bsize) < bsize) {
19996c8483Yuri Pankov			perror("read");
20096c8483Yuri Pankov			exit(8);
20196c8483Yuri Pankov		}
20296c8483Yuri Pankov
20396c8483Yuri Pankov		if (memcmp(buf, rbuf, bsize) != 0) {
20496c8483Yuri Pankov			perror("memcmp");
20596c8483Yuri Pankov			exit(9);
20696c8483Yuri Pankov		}
20796c8483Yuri Pankov	}
20896c8483Yuri Pankov	if (vflag) {
20996c8483Yuri Pankov		(void) fprintf(stderr,
21096c8483Yuri Pankov		    "Wrote to offset %jd\n", (intmax_t)(offset + roffset));
21196c8483Yuri Pankov		if (rflag) {
21296c8483Yuri Pankov			(void) fprintf(stderr,
21396c8483Yuri Pankov			    "Read back from offset %jd\n",
21496c8483Yuri Pankov			    (intmax_t)(offset + roffset));
21596c8483Yuri Pankov		}
21696c8483Yuri Pankov	}
21796c8483Yuri Pankov
21896c8483Yuri Pankov	(void) free(buf);
21996c8483Yuri Pankov	(void) free(rbuf);
22096c8483Yuri Pankov}
22196c8483Yuri Pankov
22296c8483Yuri Pankovstatic void
22396c8483Yuri Pankovdo_trunc(int fd)
22496c8483Yuri Pankov{
22596c8483Yuri Pankov	off_t   roffset = 0;
22696c8483Yuri Pankov
22796c8483Yuri Pankov	roffset = random() % fsize;
22896c8483Yuri Pankov	if (ftruncate64(fd, (offset + roffset))  < 0) {
22996c8483Yuri Pankov		perror("truncate");
23096c8483Yuri Pankov		exit(7);
23196c8483Yuri Pankov	}
23296c8483Yuri Pankov
23396c8483Yuri Pankov	if (vflag) {
23496c8483Yuri Pankov		(void) fprintf(stderr,
23596c8483Yuri Pankov		    "Truncated at offset %jd\n",
23696c8483Yuri Pankov		    (intmax_t)(offset + roffset));
23796c8483Yuri Pankov	}
23896c8483Yuri Pankov}