1 /*
2 * Copyright (c) 2016 Oracle and/or its affiliates. All Rights Reserved.
3 * Copyright (c) International Business Machines Corp., 2002
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it would be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * DESCRIPTION
19 * Copy the contents of the input file to output file using direct read
20 * and direct write. The input file size is numblks*bufsize.
21 * The read and write calls use bufsize to perform IO. Input and output
22 * files can be specified through commandline and is useful for running
23 * test with raw devices as files.
24 *
25 * USAGE
26 * diotest1 [-b bufsize] [-n numblks] [-i infile] [-o outfile]
27 *
28 * History
29 * 04/22/2002 Narasimha Sharoff nsharoff@us.ibm.com
30 */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <signal.h>
36 #include <string.h>
37 #include <fcntl.h>
38 #include <errno.h>
39
40 #include "diotest_routines.h"
41
42 #include "test.h"
43 #include "safe_macros.h"
44
45 char *TCID = "diotest01"; /* Test program identifier. */
46 int TST_TOTAL = 1; /* Total number of test conditions */
47
48 #ifdef O_DIRECT
49
50 #define BUFSIZE 8192
51 #define NBLKS 20
52 #define LEN 30
53 #define TRUE 1
54
55 static char infile[LEN]; /* Input file. Default "infile" */
56 static char outfile[LEN]; /* Output file. Default "outfile" */
57 static int fd1, fd2;
58
59 /*
60 * prg_usage: display the program usage.
61 */
prg_usage(void)62 void prg_usage(void)
63 {
64 fprintf(stderr,
65 "Usage: diotest1 [-b bufsize] [-n numblks] [-i infile] [-o outfile]\n");
66 tst_brkm(TBROK, NULL, "usage");
67 }
68
cleanup(void)69 void cleanup(void)
70 {
71 if (fd1 > 0)
72 close(fd1);
73 if (fd2 > 0)
74 close(fd2);
75
76 tst_rmdir();
77 }
78
main(int argc,char * argv[])79 int main(int argc, char *argv[])
80 {
81 int bufsize = BUFSIZE; /* Buffer size. Default 8k */
82 int numblks = NBLKS; /* Number of blocks. Default 20 */
83 int i, n, offset;
84 char *buf;
85
86 /* Options */
87 strcpy(infile, "infile"); /* Default input file */
88 strcpy(outfile, "outfile"); /* Default outfile file */
89 while ((i = getopt(argc, argv, "b:n:i:o:")) != -1) {
90 switch (i) {
91 case 'b':
92 if ((bufsize = atoi(optarg)) <= 0) {
93 fprintf(stderr, "bufsize must be > 0\n");
94 prg_usage();
95 }
96 if (bufsize % 4096 != 0) {
97 fprintf(stderr,
98 "bufsize must be multiple of 4k\n");
99 prg_usage();
100 }
101 break;
102 case 'n':
103 if ((numblks = atoi(optarg)) <= 0) {
104 fprintf(stderr, "numblks must be > 0\n");
105 prg_usage();
106 }
107 break;
108 case 'i':
109 strcpy(infile, optarg);
110 break;
111 case 'o':
112 strcpy(outfile, optarg);
113 break;
114 default:
115 prg_usage();
116 }
117 }
118
119 tst_tmpdir();
120
121 /* Test for filesystem support of O_DIRECT */
122 int fd = open(infile, O_DIRECT | O_RDWR | O_CREAT, 0666);
123
124 if (fd < 0)
125 tst_brkm(TCONF, cleanup, "O_DIRECT not supported by FS");
126 SAFE_CLOSE(cleanup, fd);
127
128 /* Open files */
129 fd1 = SAFE_OPEN(cleanup, infile, O_DIRECT | O_RDWR | O_CREAT, 0666);
130 fd2 = SAFE_OPEN(cleanup, outfile, O_DIRECT | O_RDWR | O_CREAT, 0666);
131
132 /* Allocate for buf, Create input file */
133 buf = valloc(bufsize);
134
135 if (!buf)
136 tst_brkm(TFAIL | TERRNO, cleanup, "valloc() failed");
137
138 for (i = 0; i < numblks; i++) {
139 fillbuf(buf, bufsize, (char)(i % 256));
140 SAFE_WRITE(cleanup, SAFE_WRITE_ALL, fd1, buf, bufsize);
141 }
142
143 /* Copy infile to outfile using direct read and direct write */
144 offset = 0;
145 SAFE_LSEEK(cleanup, fd1, offset, SEEK_SET);
146
147 while ((n = read(fd1, buf, bufsize)) > 0) {
148 SAFE_LSEEK(cleanup, fd2, offset, SEEK_SET);
149
150 SAFE_WRITE(cleanup, SAFE_WRITE_ALL, fd2, buf, n);
151
152 offset += n;
153 SAFE_LSEEK(cleanup, fd1, offset, SEEK_SET);
154 }
155
156 /* Verify */
157 if (filecmp(infile, outfile) != 0) {
158 tst_brkm(TFAIL, cleanup, "file compare failed for %s and %s",
159 infile, outfile);
160 }
161
162 tst_resm(TPASS, "Test passed");
163
164 cleanup();
165 tst_exit();
166 }
167
168 #else /* O_DIRECT */
169
main()170 int main()
171 {
172 tst_brkm(TCONF, NULL, "O_DIRECT is not defined.");
173 }
174 #endif /* O_DIRECT */
175