1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31 *
32 */
33 /* $Id: asyncio02.c,v 1.6 2009/08/28 11:17:39 vapier Exp $ */
34 /************************************************************
35 * OS Test - Silicon Graphics, Inc.
36 * Mendota Heights, Minnesota
37 *
38 * TEST IDENTIFIER: aiotcs02: write/close flushes data to the file
39 *
40 * PARENT DOCUMENT: aiotds01: kernel i/o
41 *
42 * AUTHOR: Barrie Kletscher
43 *
44 * CO-PILOT: Dave Baumgartner
45 *
46 * TEST ITEMS:
47 * for each open flags set used:
48 * 1. Multiple writes to a file work as specified for
49 * more than BUFSIZ bytes.
50 * 2. Multiple writes to a file work as specified for
51 * BUFSIZ bytes.
52 * 3. Multiple writes to a file work as specified for
53 * lower than BUFSIZ bytes.
54 *
55 * INPUT SPECIFICATIONS:
56 * Standard parse_opts supported options.
57 *$
58 * OUTPUT SPECIFICATIONS
59 * Standard tst_res output format
60 *
61 * ENVIRONMENTAL NEEDS:
62 * This program uses the environment variable TMPDIR for the location
63 * of the temporary directory.
64 *
65 *
66 * SPECIAL PROCEDURAL REQUIREMENTS:
67 * The program must be linked with tst_*.o and parse_opts.o.
68 *
69 * INTERCASE DEPENDENCIES:
70 * NONE.
71 *
72 * DETAILED DESCRIPTION:
73 * Attempt to get some memory to work with.
74 * Call testrun writing (BUFSIZ + 1) bytes
75 * Call testrun writing BUFSIZ bytes
76 * Repeated call to testrun() with decreasing write sizes
77 * less than BUFSIZ
78 * End
79 *
80 * Start testrun()
81 * Attempt to open a temporary file.
82 * Write the memory to the file.
83 * Attempt to close the file which also flushes the buffers.
84 * Now check to see if the number of bytes written is the
85 * same as the number of bytes in the file.
86 * Cleanup
87 *
88 * BUGS:
89 * NONE.
90 *
91 ************************************************************/
92
93 #include <fcntl.h>
94 #include <sys/types.h>
95 #include <sys/stat.h>
96 #include <sys/signal.h>
97 #include <errno.h>
98 #include <stdlib.h>
99 #include "test.h"
100
101 #define FLAG O_RDWR | O_CREAT | O_TRUNC /* Flags used when opening temp tile */
102 #define MODE 0777 /* Mode to open file with */
103 #define WRITES 10 /* Number of times buffer is written */
104 #define DECR 1000 /* Number of bytes decremented between */
105 /* Calls to testrun() */
106 #define OK -1 /* Return value from testrun() */
107
108 #define FNAME1 "aio02.1"
109 #define FNAME2 "aio02.2"
110 #define FNAME3 "aio02.3"
111
112 #define ERR_MSG1 "Bytes in file not equal to bytes written."
113 #define ERR_MSG2 "Bytes in file (%d) not equal to bytes written (%d)."
114
115 char *dp; /* pointer to area of memory */
116
117 void setup();
118 void cleanup();
119 int testrun(int flag, int bytes, int ti);
120
121 char *TCID = "asyncio02";
122 int TST_TOTAL = 6;
123
124 char *filename; /* name of the temporary file */
125
126 char *Progname;
127 int Open_flags;
128
129 int Flags[] = {
130 O_RDWR | O_CREAT | O_TRUNC,
131 O_RDWR | O_CREAT | O_TRUNC
132 };
133
134 int Num_flags;
135
136 /***********************************************************************
137 * MAIN
138 ***********************************************************************/
main(int ac,char ** av)139 int main(int ac, char **av)
140 {
141
142 int i;
143 int ret_val;
144 int eok; /* everything is ok flag */
145 int lc;
146 int flag_cnt;
147
148 Num_flags = sizeof(Flags) / sizeof(int);
149 TST_TOTAL = 3 * Num_flags;
150
151 tst_parse_opts(ac, av, NULL, NULL);
152
153 setup();
154
155 for (lc = 0; TEST_LOOPING(lc); lc++) {
156
157 tst_count = 0;
158
159 for (flag_cnt = 0; flag_cnt < Num_flags; flag_cnt++) {
160
161 /*
162 * call testrun writing (BUFSIZ + 1) byte chunks
163 */
164
165 filename = FNAME1;
166 if (testrun(Flags[flag_cnt], BUFSIZ + 1, 1) != OK) {
167 tst_resm(TFAIL, ERR_MSG1);
168 } else {
169 tst_resm(TPASS,
170 "More than BUFSIZE bytes multiple synchronous writes to a file check out ok");
171 }
172
173 /*
174 * call testrun writing BUFSIZ byte chunks
175 */
176
177 filename = FNAME2;
178 if (testrun(Flags[flag_cnt], BUFSIZ, 2) != OK) {
179 tst_resm(TFAIL, ERR_MSG1);
180 } else {
181 tst_resm(TPASS,
182 "BUFSIZE bytes multiple synchronous writes to a file checks out ok");
183 }
184
185 /*
186 * while the byte chunks are greater than 0
187 * call testrun() with decreasing chunk sizes
188 */
189
190 filename = FNAME3;
191 eok = 1;
192 for (i = BUFSIZ - 1; i >= 0; i -= DECR) {
193 if ((ret_val =
194 testrun(Flags[flag_cnt], i, 3)) != OK) {
195 tst_resm(TFAIL, ERR_MSG2, ret_val,
196 i * WRITES);
197 }
198 }
199
200 if (eok) {
201 tst_resm(TPASS,
202 "Less than BUFSIZE bytes multiple synchronous writes to a file checks out ok");
203 }
204 }
205 }
206 cleanup();
207 tst_exit();
208 } /* end main() */
209
testrun(int flag,int bytes,int ti)210 int testrun(int flag, int bytes, int ti)
211 {
212
213 int fildes, i, ret;
214
215 struct stat buffer; /* buffer of memory required for stat command */
216
217 /*
218 * Attempt to open a temporary file.
219 */
220
221 if ((fildes = open(filename, flag, MODE)) == -1) {
222 tst_brkm(TBROK | TERRNO, cleanup, "open(%s) failed", filename);
223 }
224
225 /*
226 * Write the memory to the file.
227 */
228
229 for (i = 0; i < WRITES; i++) {
230 TEST(write(fildes, dp, (unsigned)bytes));
231
232 if (TEST_RETURN == -1) {
233 tst_brkm(TBROK | TTERRNO, cleanup, "write() failed");
234 }
235 } /* end for () */
236
237 /*
238 * Attempt to close the file which also flushes the buffers.
239 */
240
241 if (close(fildes) == -1) {
242 tst_brkm(TBROK | TERRNO, cleanup, "close() failed");
243 }
244
245 ret = OK;
246
247 /*
248 * Now check to see if the number of bytes written is the
249 * same as the number of bytes in the file.
250 */
251
252 if (stat(filename, &buffer) == -1) {
253 tst_brkm(TBROK | TERRNO, cleanup, "stat() failed");
254 }
255
256 if (buffer.st_size != (off_t) (bytes * WRITES)) {
257 ret = (int)buffer.st_size;
258 }
259
260 if (unlink(filename) == -1) {
261 tst_brkm(TBROK | TERRNO, cleanup, "unlink(%s) failed",
262 filename);
263 }
264
265 return ret;
266
267 } /* end testrun() */
268
269 /***************************************************************
270 * setup() - performs all ONE TIME setup for this test.
271 ***************************************************************/
setup(void)272 void setup(void)
273 {
274
275 tst_sig(FORK, DEF_HANDLER, cleanup);
276
277 TEST_PAUSE;
278
279 /* create a temporary directory and go to it */
280 tst_tmpdir();
281
282 /*
283 * Attempt to get some memory to work with.
284 */
285
286 if ((dp = malloc((unsigned)BUFSIZ + 1)) == NULL) {
287 tst_brkm(TBROK | TERRNO, cleanup, "malloc() failed");
288 }
289
290 }
291
292 /***************************************************************
293 * cleanup() - performs all ONE TIME cleanup for this test at
294 * completion or premature exit.
295 ***************************************************************/
cleanup(void)296 void cleanup(void)
297 {
298
299 tst_rmdir();
300 }
301