blob: 8b2f7b28df6a6853cdfe3cc7e5595c2bc41f66b0 [file] [log] [blame]
robbiew3c658152003-01-07 21:50:34 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2002
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the 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, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/*
21 * NAME
22 * pwrite04.c (ported from SPIE, section2/filesuite/pread_pwrite.c,
23 * by Airong Zhang)
24 *
25 * TEST SUMMARY
26 * Test the pwrite() system call with O_APPEND.
27 *
28 * USAGE
subrata_modak4bb656a2009-02-26 12:02:09 +000029 * pwrite04
robbiew3c658152003-01-07 21:50:34 +000030 *
31 */
32
33#define _XOPEN_SOURCE 500
34#include <stdio.h>
35#include <sys/types.h>
36#include <sys/stat.h>
37#include <unistd.h>
38#include <sys/fcntl.h>
39#include <memory.h>
40#include <errno.h>
41#include "usctest.h"
42#include "test.h"
43
44char *TCID = "pwrite04";
45int TST_TOTAL = 1;
46extern int Tst_count;
subrata_modak56207ce2009-03-23 13:35:39 +000047int local_flag;
robbiew3c658152003-01-07 21:50:34 +000048
49#define PASSED 1
50#define FAILED 0
51
subrata_modak56207ce2009-03-23 13:35:39 +000052int block_cnt = 0;
robbiew3c658152003-01-07 21:50:34 +000053
54#define K1 1024
55#define K2 (K1 * 2)
56#define K3 (K1 * 3)
57#define K4 (K1 * 4)
58#define K5 (K1 * 5)
59#define NBUFS 4
60#define DATA_FILE "pwrite04_file"
61
62char name[256], fname[256];
63
subrata_modak56207ce2009-03-23 13:35:39 +000064void init_buffers(char *[]);
robbiew3c658152003-01-07 21:50:34 +000065void l_seek(int, off_t, int, off_t);
subrata_modak24fc2132008-11-11 05:57:38 +000066static void cleanup(void);
robbiew3c658152003-01-07 21:50:34 +000067
subrata_modak4bb656a2009-02-26 12:02:09 +000068int main(int ac, char *av[])
robbiew3c658152003-01-07 21:50:34 +000069{
subrata_modak56207ce2009-03-23 13:35:39 +000070 int fd;
71 int nbytes;
72 char *wbuf[NBUFS];
73 struct stat statbuf;
74 int lc; /* loop counter */
75 char *msg; /* message returned from parse_opts */
robbiew3c658152003-01-07 21:50:34 +000076
77 strcpy(name, DATA_FILE);
78 sprintf(fname, "%s.%d", name, getpid());
79
subrata_modak56207ce2009-03-23 13:35:39 +000080 /*
81 * parse standard options
82 */
Garrett Cooper45e285d2010-11-22 12:19:25 -080083 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) {
subrata_modak56207ce2009-03-23 13:35:39 +000084 tst_resm(TBROK, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2c282152010-12-16 00:55:50 -080085
subrata_modak56207ce2009-03-23 13:35:39 +000086 }
robbiew3c658152003-01-07 21:50:34 +000087 tst_tmpdir();
88 for (lc = 0; TEST_LOOPING(lc); lc++) {
89
90 init_buffers(wbuf);
91 local_flag = PASSED;
92
93 if ((fd = open(fname, O_RDWR | O_CREAT, 0666)) < 0) {
subrata_modak56207ce2009-03-23 13:35:39 +000094 tst_resm(TBROK, "open failed: fname = %s, errno = %d",
95 fname, errno);
96 cleanup();
97 }
98 /*
99 * pwrite() K1 of data (0's) at offset 0.
100 */
101 if ((nbytes = pwrite(fd, wbuf[0], K1, 0)) != K1) {
102 tst_resm(TFAIL,
103 "pwrite at 0 failed: nbytes=%d, errno=%d",
104 nbytes, errno);
105 cleanup();
106 }
robbiew3c658152003-01-07 21:50:34 +0000107
subrata_modak56207ce2009-03-23 13:35:39 +0000108 /*
109 * We should still be at offset 0.
110 */
111 l_seek(fd, 0, SEEK_CUR, 0);
robbiew3c658152003-01-07 21:50:34 +0000112
subrata_modak56207ce2009-03-23 13:35:39 +0000113 /*
114 * lseek() to a non K boundary, just to be different.
115 */
116 l_seek(fd, K1 / 2, SEEK_SET, K1 / 2);
robbiew3c658152003-01-07 21:50:34 +0000117
subrata_modak56207ce2009-03-23 13:35:39 +0000118 /*
119 * pwrite() K1 of data (2's) at offset K2.
120 */
121 if ((nbytes = pwrite(fd, wbuf[2], K1, K2)) != K1) {
122 tst_resm(TFAIL,
123 "pwrite at K2 failed: nbytes=%d, errno=%d",
124 nbytes, errno);
125 cleanup();
126 }
robbiew3c658152003-01-07 21:50:34 +0000127
subrata_modak56207ce2009-03-23 13:35:39 +0000128 /*
129 * We should still be at our non K boundary.
130 */
131 l_seek(fd, 0, SEEK_CUR, K1 / 2);
robbiew3c658152003-01-07 21:50:34 +0000132
subrata_modak56207ce2009-03-23 13:35:39 +0000133 /*
134 * lseek() to an offset of K3.
135 */
136 l_seek(fd, K3, SEEK_SET, K3);
robbiew3c658152003-01-07 21:50:34 +0000137
subrata_modak56207ce2009-03-23 13:35:39 +0000138 /*
139 * This time use a normal write() of K1 of data (3's) which should
140 * take place at an offset of K3, moving the file pointer to K4.
141 */
142 if ((nbytes = write(fd, wbuf[3], K1)) != K1) {
143 tst_resm(TFAIL, "write failed: nbytes=%d, errno=%d",
144 nbytes, errno);
145 cleanup();
146 }
robbiew3c658152003-01-07 21:50:34 +0000147
subrata_modak56207ce2009-03-23 13:35:39 +0000148 /*
149 * We should be at offset K4.
150 */
151 l_seek(fd, 0, SEEK_CUR, K4);
robbiew3c658152003-01-07 21:50:34 +0000152
subrata_modak56207ce2009-03-23 13:35:39 +0000153 /*
154 * pwrite() K1 of data (1's) at offset K1.
155 */
156 if ((nbytes = pwrite(fd, wbuf[1], K1, K1)) != K1) {
157 tst_resm(TFAIL, "pwrite failed: nbytes=%d, errno=%d",
158 nbytes, errno);
159 cleanup();
160 }
robbiew3c658152003-01-07 21:50:34 +0000161
162 /*--------------------------------------------------------------*/
163
164 /*
165 * Now test that O_APPEND takes precedence over any
166 * offset specified by pwrite(), but that the file
167 * pointer remains unchanged. First, close then reopen
168 * the file and ensure it is already K4 in length and
169 * set the file pointer to it's midpoint, K2.
170 */
171 close(fd);
172 if ((fd = open(fname, O_RDWR | O_APPEND, 0666)) < 0) {
vapiercff4af02006-02-11 04:46:30 +0000173 tst_resm(TBROK, "open failed: fname = %s, errno = %d",
subrata_modak56207ce2009-03-23 13:35:39 +0000174 fname, errno);
subrata_modak814e03c2008-11-11 06:44:51 +0000175 cleanup();
robbiew3c658152003-01-07 21:50:34 +0000176 }
177 if (fstat(fd, &statbuf) == -1) {
vapiercff4af02006-02-11 04:46:30 +0000178 tst_resm(TFAIL, "fstat failed: errno = %d", errno);
subrata_modak814e03c2008-11-11 06:44:51 +0000179 cleanup();
robbiew3c658152003-01-07 21:50:34 +0000180 }
181 if (statbuf.st_size != K4) {
subrata_modak56207ce2009-03-23 13:35:39 +0000182 tst_resm(TFAIL, "file size is %ld != K4",
183 statbuf.st_size);
subrata_modak814e03c2008-11-11 06:44:51 +0000184 cleanup();
robbiew3c658152003-01-07 21:50:34 +0000185 }
186 l_seek(fd, K2, SEEK_SET, K2);
187
188 /*
189 * Finally, pwrite() some K1 of data at offset 0.
190 * What we should end up with is:
subrata_modak56207ce2009-03-23 13:35:39 +0000191 * -The file pointer should still be at K2.
192 * -The data should have been written to the end
193 * of the file (O_APPEND) and should be K5 in size.
subrata_modakbdbaec52009-02-26 12:14:51 +0000194 */
robbiew3c658152003-01-07 21:50:34 +0000195 if ((nbytes = pwrite(fd, wbuf[0], K1, 0)) != K1) {
subrata_modak56207ce2009-03-23 13:35:39 +0000196 tst_resm(TFAIL,
197 "pwrite at 0 failed: nbytes=%d, errno=%d",
198 nbytes, errno);
Garrett Cooper2c282152010-12-16 00:55:50 -0800199
robbiew3c658152003-01-07 21:50:34 +0000200 }
201 l_seek(fd, 0, SEEK_CUR, K2);
202 if (fstat(fd, &statbuf) == -1) {
vapiercff4af02006-02-11 04:46:30 +0000203 tst_resm(TFAIL, "fstat failed: errno = %d", errno);
Garrett Cooper2c282152010-12-16 00:55:50 -0800204
robbiew3c658152003-01-07 21:50:34 +0000205 }
206 if (statbuf.st_size != K5) {
subrata_modak56207ce2009-03-23 13:35:39 +0000207 tst_resm(TFAIL, "file size is %ld != K4",
208 statbuf.st_size);
Garrett Cooper2c282152010-12-16 00:55:50 -0800209
robbiew3c658152003-01-07 21:50:34 +0000210 }
subrata_modak56207ce2009-03-23 13:35:39 +0000211 tst_resm(TPASS, "O_APPEND test passed.");
robbiew3c658152003-01-07 21:50:34 +0000212
213 /*------------------------------------------------------------------------*/
214
215 close(fd);
216 unlink(fname);
subrata_modak56207ce2009-03-23 13:35:39 +0000217 } /* end for */
subrata_modak814e03c2008-11-11 06:44:51 +0000218 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -0800219
robbiew3c658152003-01-07 21:50:34 +0000220}
221
222/*------------------------------------------------------------------------*/
223
224/*
225 * init_buffers() allocates wbuf[] array
226 * as follows:
227 * wbuf[0] has 0's, wbuf[1] has 1's, wbuf[2] has 2's, and wbuf[3] has 3's.
228 */
229void init_buffers(char *wbuf[])
230{
subrata_modak4bb656a2009-02-26 12:02:09 +0000231 int i;
robbiew3c658152003-01-07 21:50:34 +0000232
subrata_modak56207ce2009-03-23 13:35:39 +0000233 for (i = 0; i < NBUFS; i++) {
robbiew3c658152003-01-07 21:50:34 +0000234 wbuf[i] = (char *)malloc(K1);
235 if (wbuf[i] == NULL) {
vapiercff4af02006-02-11 04:46:30 +0000236 tst_resm(TBROK, "ib: malloc failed: errno=%d", errno);
robbiew3c658152003-01-07 21:50:34 +0000237 tst_exit();
238 }
239 memset(wbuf[i], i, K1);
240 }
241}
242
243/*
244 * l_seek() is a local front end to lseek().
245 * "checkoff" is the offset at which we believe we should be at.
246 * Used to validate pwrite doesn't move the offset.
247 */
subrata_modak56207ce2009-03-23 13:35:39 +0000248void l_seek(int fdesc, off_t offset, int whence, off_t checkoff)
robbiew3c658152003-01-07 21:50:34 +0000249{
250 off_t offloc;
251
252 if ((offloc = lseek(fdesc, offset, whence)) != checkoff) {
vapiercff4af02006-02-11 04:46:30 +0000253 tst_resm(TFAIL, "(%ld = lseek(%d, %ld, %d)) != %ld) errno = %d",
subrata_modak56207ce2009-03-23 13:35:39 +0000254 offloc, fdesc, offset, whence, checkoff, errno);
robbiew3c658152003-01-07 21:50:34 +0000255 tst_exit();
256 }
257}
258
subrata_modak814e03c2008-11-11 06:44:51 +0000259/*
260 * cleanup() - Performs all ONE TIME cleanup for this test at
261 * completion or premature exit.
262 *
263 * Print test timing stats and errno log if test executed with options.
264 * Close the testfile if still opened.
265 * Remove temporary directory and sub-directories/files under it
266 * created during setup().
267 * Exit the test program with normal exit code.
268 */
269void cleanup()
270{
271 /*
272 * print timing stats if that option was specified.
273 * print errno log if that option was specified.
274 */
275 TEST_CLEANUP;
276
subrata_modak814e03c2008-11-11 06:44:51 +0000277 tst_rmdir();
278
Garrett Cooper2c282152010-12-16 00:55:50 -0800279}