1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci *
3f08c3bdfSopenharmony_ci *   Copyright (c) CHANG Industry, Inc., 2004
4f08c3bdfSopenharmony_ci *
5f08c3bdfSopenharmony_ci *   This program is free software;  you can redistribute it and/or modify
6f08c3bdfSopenharmony_ci *   it under the terms of the GNU General Public License as published by
7f08c3bdfSopenharmony_ci *   the Free Software Foundation; either version 2 of the License, or
8f08c3bdfSopenharmony_ci *   (at your option) any later version.
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci *   This program is distributed in the hope that it will be useful,
11f08c3bdfSopenharmony_ci *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12f08c3bdfSopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13f08c3bdfSopenharmony_ci *   the GNU General Public License for more details.
14f08c3bdfSopenharmony_ci *
15f08c3bdfSopenharmony_ci *   You should have received a copy of the GNU General Public License
16f08c3bdfSopenharmony_ci *   along with this program;  if not, write to the Free Software
17f08c3bdfSopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18f08c3bdfSopenharmony_ci */
19f08c3bdfSopenharmony_ci
20f08c3bdfSopenharmony_ci/*
21f08c3bdfSopenharmony_ci *  FILE        : writetest.c
22f08c3bdfSopenharmony_ci *  DESCRIPTION : The purpose of this test is to verify that writes to
23f08c3bdfSopenharmony_ci *                disk occur without corruption.  It writes one 1MB
24f08c3bdfSopenharmony_ci *                buffer at a time, where each byte in the buffer is
25f08c3bdfSopenharmony_ci *                generated from a random number.  Once done
26f08c3bdfSopenharmony_ci *                completed, the file is re-opened, the random number
27f08c3bdfSopenharmony_ci *                generator is re-seeded, and the file is verified.
28f08c3bdfSopenharmony_ci *
29f08c3bdfSopenharmony_ci *  HISTORY:
30f08c3bdfSopenharmony_ci *   05/12/2004 : Written by Danny Sung <dannys@changind.com> to
31f08c3bdfSopenharmony_ci *                verify integrity of disk writes.
32f08c3bdfSopenharmony_ci *
33f08c3bdfSopenharmony_ci */
34f08c3bdfSopenharmony_ci
35f08c3bdfSopenharmony_ci#include <fcntl.h>
36f08c3bdfSopenharmony_ci#include <getopt.h>
37f08c3bdfSopenharmony_ci#include <stdarg.h>
38f08c3bdfSopenharmony_ci#include <stdint.h>
39f08c3bdfSopenharmony_ci#include <stdio.h>
40f08c3bdfSopenharmony_ci#include <stdlib.h>
41f08c3bdfSopenharmony_ci#include <string.h>
42f08c3bdfSopenharmony_ci#include <time.h>
43f08c3bdfSopenharmony_ci#include <unistd.h>
44f08c3bdfSopenharmony_ci
45f08c3bdfSopenharmony_ci#include "test.h"
46f08c3bdfSopenharmony_ci
47f08c3bdfSopenharmony_ci#define BLOCKSIZE (1024*1024)
48f08c3bdfSopenharmony_ci#define FILE_OUT    "fileout"
49f08c3bdfSopenharmony_ci#define FILE_MODE   0644
50f08c3bdfSopenharmony_ci#define MAX_FILENAME_LEN 1024
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_ciint Verbosity = 0;
53f08c3bdfSopenharmony_ciint DefaultSeed = 0;
54f08c3bdfSopenharmony_cichar Filename[MAX_FILENAME_LEN] = FILE_OUT;
55f08c3bdfSopenharmony_cioff_t NumBlocks = 1;
56f08c3bdfSopenharmony_cichar *TCID = "writetest";
57f08c3bdfSopenharmony_ciint TST_TOTAL = 2;
58f08c3bdfSopenharmony_ci
59f08c3bdfSopenharmony_civoid buf_init(void)
60f08c3bdfSopenharmony_ci{
61f08c3bdfSopenharmony_ci	static int seed = 0;
62f08c3bdfSopenharmony_ci	if (seed == 0)
63f08c3bdfSopenharmony_ci		seed = DefaultSeed;
64f08c3bdfSopenharmony_ci	srand(seed);
65f08c3bdfSopenharmony_ci}
66f08c3bdfSopenharmony_ci
67f08c3bdfSopenharmony_civoid buf_fill(uint8_t * buf)
68f08c3bdfSopenharmony_ci{
69f08c3bdfSopenharmony_ci	int i;
70f08c3bdfSopenharmony_ci	for (i = 0; i < BLOCKSIZE; i++) {
71f08c3bdfSopenharmony_ci		*buf = (rand() & 0xff);
72f08c3bdfSopenharmony_ci		buf++;
73f08c3bdfSopenharmony_ci	}
74f08c3bdfSopenharmony_ci}
75f08c3bdfSopenharmony_ci
76f08c3bdfSopenharmony_ciint write_file(off_t num_blocks, const char *filename)
77f08c3bdfSopenharmony_ci{
78f08c3bdfSopenharmony_ci	int fd;
79f08c3bdfSopenharmony_ci	int ret = 0;
80f08c3bdfSopenharmony_ci	off_t block;
81f08c3bdfSopenharmony_ci	uint8_t buf[BLOCKSIZE];
82f08c3bdfSopenharmony_ci
83f08c3bdfSopenharmony_ci	fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE,
84f08c3bdfSopenharmony_ci		  FILE_MODE);
85f08c3bdfSopenharmony_ci	if (fd < 0) {
86f08c3bdfSopenharmony_ci		perror(TCID);
87f08c3bdfSopenharmony_ci		return (-1);
88f08c3bdfSopenharmony_ci	}
89f08c3bdfSopenharmony_ci	for (block = 0; block < num_blocks; block++) {
90f08c3bdfSopenharmony_ci		int rv;
91f08c3bdfSopenharmony_ci		if (Verbosity > 2)
92f08c3bdfSopenharmony_ci			tst_resm(TINFO, "Block: %lld/%lld  (%3lld%%)\r",
93f08c3bdfSopenharmony_ci				 (long long int)block,
94f08c3bdfSopenharmony_ci				 (long long int)num_blocks,
95f08c3bdfSopenharmony_ci				 (long long int)(block * 100 / num_blocks));
96f08c3bdfSopenharmony_ci		buf_fill(buf);
97f08c3bdfSopenharmony_ci		rv = write(fd, buf, BLOCKSIZE);
98f08c3bdfSopenharmony_ci		if (rv != BLOCKSIZE) {
99f08c3bdfSopenharmony_ci			ret = -1;
100f08c3bdfSopenharmony_ci			break;
101f08c3bdfSopenharmony_ci		}
102f08c3bdfSopenharmony_ci	}
103f08c3bdfSopenharmony_ci	if (Verbosity > 2)
104f08c3bdfSopenharmony_ci		tst_resm(TINFO, "Block: %lld/%lld  (%3lld%%)\r",
105f08c3bdfSopenharmony_ci			 (long long int)block, (long long int)num_blocks,
106f08c3bdfSopenharmony_ci			 (long long int)(block * 100 / num_blocks));
107f08c3bdfSopenharmony_ci	close(fd);
108f08c3bdfSopenharmony_ci	return (ret);
109f08c3bdfSopenharmony_ci}
110f08c3bdfSopenharmony_ci
111f08c3bdfSopenharmony_ciint verify_file(off_t num_blocks, const char *filename)
112f08c3bdfSopenharmony_ci{
113f08c3bdfSopenharmony_ci	int fd;
114f08c3bdfSopenharmony_ci	int ret = 0;
115f08c3bdfSopenharmony_ci	off_t block;
116f08c3bdfSopenharmony_ci	uint8_t buf_actual[BLOCKSIZE];
117f08c3bdfSopenharmony_ci	char buf_read[BLOCKSIZE];
118f08c3bdfSopenharmony_ci
119f08c3bdfSopenharmony_ci	fd = open(filename, O_RDONLY);
120f08c3bdfSopenharmony_ci	if (fd < 0) {
121f08c3bdfSopenharmony_ci		perror(TCID);
122f08c3bdfSopenharmony_ci		return (-1);
123f08c3bdfSopenharmony_ci	}
124f08c3bdfSopenharmony_ci	for (block = 0; block < num_blocks; block++) {
125f08c3bdfSopenharmony_ci		int rv;
126f08c3bdfSopenharmony_ci		int n;
127f08c3bdfSopenharmony_ci		if (Verbosity > 2)
128f08c3bdfSopenharmony_ci			tst_resm(TINFO, "Block: %lld/%lld  (%3lld%%)\r",
129f08c3bdfSopenharmony_ci				 (long long int)block,
130f08c3bdfSopenharmony_ci				 (long long int)num_blocks,
131f08c3bdfSopenharmony_ci				 (long long int)(block * 100 / num_blocks));
132f08c3bdfSopenharmony_ci		buf_fill(buf_actual);
133f08c3bdfSopenharmony_ci		rv = read(fd, buf_read, BLOCKSIZE);
134f08c3bdfSopenharmony_ci		if (rv != BLOCKSIZE) {
135f08c3bdfSopenharmony_ci			ret = -1;
136f08c3bdfSopenharmony_ci			break;
137f08c3bdfSopenharmony_ci		}
138f08c3bdfSopenharmony_ci		for (n = 0; n < BLOCKSIZE; n++) {
139f08c3bdfSopenharmony_ci			int ba, br;
140f08c3bdfSopenharmony_ci			ba = buf_actual[n] & 0xff;
141f08c3bdfSopenharmony_ci			br = buf_read[n] & 0xff;
142f08c3bdfSopenharmony_ci			if (ba != br) {
143f08c3bdfSopenharmony_ci				if (Verbosity > 2)
144f08c3bdfSopenharmony_ci					tst_resm(TINFO,
145f08c3bdfSopenharmony_ci						 "Mismatch: block=%lld +%d bytes offset=%lld read: %02xh actual: %02xh\n",
146f08c3bdfSopenharmony_ci						 (long long int)block, n,
147f08c3bdfSopenharmony_ci						 (long long
148f08c3bdfSopenharmony_ci						  int)((block * BLOCKSIZE) + n),
149f08c3bdfSopenharmony_ci						 br, ba);
150f08c3bdfSopenharmony_ci				ret++;
151f08c3bdfSopenharmony_ci			}
152f08c3bdfSopenharmony_ci		}
153f08c3bdfSopenharmony_ci	}
154f08c3bdfSopenharmony_ci	close(fd);
155f08c3bdfSopenharmony_ci	if (Verbosity > 2)
156f08c3bdfSopenharmony_ci		tst_resm(TINFO, "Block: %lld/%lld  (%3lld%%)\r",
157f08c3bdfSopenharmony_ci			 (long long int)block, (long long int)num_blocks,
158f08c3bdfSopenharmony_ci			 (long long int)(block * 100 / num_blocks));
159f08c3bdfSopenharmony_ci	return (ret);
160f08c3bdfSopenharmony_ci}
161f08c3bdfSopenharmony_ci
162f08c3bdfSopenharmony_civoid usage(void)
163f08c3bdfSopenharmony_ci{
164f08c3bdfSopenharmony_ci	printf("%s [-v] [-b blocks] [-s seed] [-o filename]\n", TCID);
165f08c3bdfSopenharmony_ci	printf("\n"
166f08c3bdfSopenharmony_ci	       "   -v          - increase verbosity level\n"
167f08c3bdfSopenharmony_ci	       "   blocks      - number of blocks to write\n"
168f08c3bdfSopenharmony_ci	       "   seed        - seed to use (0 to use timestamp)\n"
169f08c3bdfSopenharmony_ci	       "   filename    - name of output file\n");
170f08c3bdfSopenharmony_ci}
171f08c3bdfSopenharmony_ci
172f08c3bdfSopenharmony_civoid parse_args(int argc, char **argv)
173f08c3bdfSopenharmony_ci{
174f08c3bdfSopenharmony_ci	int c;
175f08c3bdfSopenharmony_ci	TCID = argv[0];
176f08c3bdfSopenharmony_ci
177f08c3bdfSopenharmony_ci	while (1) {
178f08c3bdfSopenharmony_ci		int option_index = 0;
179f08c3bdfSopenharmony_ci		static struct option long_options[] = {
180f08c3bdfSopenharmony_ci			{"blocks", 1, 0, 'b'},
181f08c3bdfSopenharmony_ci			{"out", 1, 0, 'o'},
182f08c3bdfSopenharmony_ci			{"seed", 1, 0, 's'},
183f08c3bdfSopenharmony_ci			{"verbose", 0, 0, 'v'},
184f08c3bdfSopenharmony_ci			{"help", 0, 0, 'h'},
185f08c3bdfSopenharmony_ci			{0, 0, 0, 0}
186f08c3bdfSopenharmony_ci		};
187f08c3bdfSopenharmony_ci		c = getopt_long(argc, argv, "hvb:o:s:", long_options,
188f08c3bdfSopenharmony_ci				&option_index);
189f08c3bdfSopenharmony_ci		if (c == -1)
190f08c3bdfSopenharmony_ci			break;
191f08c3bdfSopenharmony_ci		switch (c) {
192f08c3bdfSopenharmony_ci		case 'b':
193f08c3bdfSopenharmony_ci			NumBlocks = strtoul(optarg, NULL, 0);
194f08c3bdfSopenharmony_ci			break;
195f08c3bdfSopenharmony_ci		case 'o':
196f08c3bdfSopenharmony_ci			strncpy(Filename, optarg, MAX_FILENAME_LEN);
197f08c3bdfSopenharmony_ci			break;
198f08c3bdfSopenharmony_ci		case 's':
199f08c3bdfSopenharmony_ci			DefaultSeed = strtoul(optarg, NULL, 0);
200f08c3bdfSopenharmony_ci			break;
201f08c3bdfSopenharmony_ci		case 'v':
202f08c3bdfSopenharmony_ci			Verbosity++;
203f08c3bdfSopenharmony_ci			break;
204f08c3bdfSopenharmony_ci		case 'h':
205f08c3bdfSopenharmony_ci		default:
206f08c3bdfSopenharmony_ci			usage();
207f08c3bdfSopenharmony_ci			exit(-1);
208f08c3bdfSopenharmony_ci		}
209f08c3bdfSopenharmony_ci	}
210f08c3bdfSopenharmony_ci}
211f08c3bdfSopenharmony_ci
212f08c3bdfSopenharmony_civoid setup()
213f08c3bdfSopenharmony_ci{
214f08c3bdfSopenharmony_ci	tst_tmpdir();
215f08c3bdfSopenharmony_ci
216f08c3bdfSopenharmony_ci}
217f08c3bdfSopenharmony_ci
218f08c3bdfSopenharmony_civoid cleanup(void)
219f08c3bdfSopenharmony_ci{
220f08c3bdfSopenharmony_ci	tst_rmdir();
221f08c3bdfSopenharmony_ci	tst_exit();
222f08c3bdfSopenharmony_ci}
223f08c3bdfSopenharmony_ci
224f08c3bdfSopenharmony_ciint main(int argc, char *argv[])
225f08c3bdfSopenharmony_ci{
226f08c3bdfSopenharmony_ci	int rv;
227f08c3bdfSopenharmony_ci
228f08c3bdfSopenharmony_ci	setup();
229f08c3bdfSopenharmony_ci
230f08c3bdfSopenharmony_ci	DefaultSeed = time(NULL);
231f08c3bdfSopenharmony_ci	parse_args(argc, argv);
232f08c3bdfSopenharmony_ci	tst_resm(TINFO, "Blocks:       %lld\n", (long long int)NumBlocks);
233f08c3bdfSopenharmony_ci	tst_resm(TINFO, "Seed:         %d\n", DefaultSeed);
234f08c3bdfSopenharmony_ci	tst_resm(TINFO, "Output file: '%s'\n", Filename);
235f08c3bdfSopenharmony_ci
236f08c3bdfSopenharmony_ci	tst_resm(TINFO, "Writing %lld blocks of %d bytes to '%s'\n",
237f08c3bdfSopenharmony_ci		 (long long int)NumBlocks, BLOCKSIZE, Filename);
238f08c3bdfSopenharmony_ci	buf_init();
239f08c3bdfSopenharmony_ci	rv = write_file(NumBlocks, Filename);
240f08c3bdfSopenharmony_ci	if (rv == 0) {
241f08c3bdfSopenharmony_ci		tst_resm(TPASS, "Write: Success");
242f08c3bdfSopenharmony_ci	} else {
243f08c3bdfSopenharmony_ci		tst_resm(TFAIL, "Write: Failure");
244f08c3bdfSopenharmony_ci	}
245f08c3bdfSopenharmony_ci
246f08c3bdfSopenharmony_ci	tst_resm(TINFO, "Verifying %lld blocks in '%s'\n",
247f08c3bdfSopenharmony_ci		 (long long int)NumBlocks, Filename);
248f08c3bdfSopenharmony_ci	buf_init();
249f08c3bdfSopenharmony_ci	rv = verify_file(NumBlocks, Filename);
250f08c3bdfSopenharmony_ci	if (rv == 0) {
251f08c3bdfSopenharmony_ci		tst_resm(TPASS, "Verify: Success\n");
252f08c3bdfSopenharmony_ci	} else {
253f08c3bdfSopenharmony_ci		tst_resm(TFAIL, "Verify: Failure");
254f08c3bdfSopenharmony_ci		tst_resm(TINFO, "Total mismatches: %d bytes\n", rv);
255f08c3bdfSopenharmony_ci	}
256f08c3bdfSopenharmony_ci
257f08c3bdfSopenharmony_ci	cleanup();
258f08c3bdfSopenharmony_ci	return 0;
259f08c3bdfSopenharmony_ci}
260