1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "apr_file_io.h"
18 #include "apr_file_info.h"
19 #include "apr_network_io.h"
20 #include "apr_errno.h"
21 #include "apr_general.h"
22 #include "apr_poll.h"
23 #include "apr_lib.h"
24 #include "testutil.h"
25
26 #define DIRNAME "data"
27 #define FILENAME DIRNAME "/file_datafile.txt"
28 #define TESTSTR "This is the file data file."
29
30 #define TESTREAD_BLKSIZE 1024
31 #define APR_BUFFERSIZE 4096 /* This should match APR's buffer size. */
32
33
34
test_open_noreadwrite(abts_case * tc,void * data)35 static void test_open_noreadwrite(abts_case *tc, void *data)
36 {
37 apr_status_t rv;
38 apr_file_t *thefile = NULL;
39
40 rv = apr_file_open(&thefile, FILENAME,
41 APR_FOPEN_CREATE | APR_FOPEN_EXCL,
42 APR_UREAD | APR_UWRITE | APR_GREAD, p);
43 ABTS_TRUE(tc, rv != APR_SUCCESS);
44 ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EACCES(rv));
45 ABTS_PTR_EQUAL(tc, NULL, thefile);
46 }
47
test_open_excl(abts_case * tc,void * data)48 static void test_open_excl(abts_case *tc, void *data)
49 {
50 apr_status_t rv;
51 apr_file_t *thefile = NULL;
52
53 rv = apr_file_open(&thefile, FILENAME,
54 APR_FOPEN_CREATE | APR_FOPEN_EXCL | APR_FOPEN_WRITE,
55 APR_UREAD | APR_UWRITE | APR_GREAD, p);
56 ABTS_TRUE(tc, rv != APR_SUCCESS);
57 ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EEXIST(rv));
58 ABTS_PTR_EQUAL(tc, NULL, thefile);
59 }
60
test_open_read(abts_case * tc,void * data)61 static void test_open_read(abts_case *tc, void *data)
62 {
63 apr_status_t rv;
64 apr_file_t *filetest = NULL;
65
66 rv = apr_file_open(&filetest, FILENAME,
67 APR_FOPEN_READ,
68 APR_UREAD | APR_UWRITE | APR_GREAD, p);
69 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
70 ABTS_PTR_NOTNULL(tc, filetest);
71 apr_file_close(filetest);
72 }
73
link_existing(abts_case * tc,void * data)74 static void link_existing(abts_case *tc, void *data)
75 {
76 apr_status_t rv;
77
78 rv = apr_file_link("data/file_datafile.txt", "data/file_datafile2.txt");
79 apr_file_remove("data/file_datafile2.txt", p);
80 ABTS_ASSERT(tc, "Couldn't create hardlink to file", rv == APR_SUCCESS);
81 }
82
link_nonexisting(abts_case * tc,void * data)83 static void link_nonexisting(abts_case *tc, void *data)
84 {
85 apr_status_t rv;
86
87 rv = apr_file_link("data/does_not_exist.txt", "data/fake.txt");
88 ABTS_ASSERT(tc, "", rv != APR_SUCCESS);
89 }
90
test_read(abts_case * tc,void * data)91 static void test_read(abts_case *tc, void *data)
92 {
93 apr_status_t rv;
94 apr_size_t nbytes = 256;
95 char *str = apr_pcalloc(p, nbytes + 1);
96 apr_file_t *filetest = NULL;
97
98 rv = apr_file_open(&filetest, FILENAME,
99 APR_FOPEN_READ,
100 APR_UREAD | APR_UWRITE | APR_GREAD, p);
101
102 APR_ASSERT_SUCCESS(tc, "Opening test file " FILENAME, rv);
103 rv = apr_file_read(filetest, str, &nbytes);
104 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
105 ABTS_SIZE_EQUAL(tc, strlen(TESTSTR), nbytes);
106 ABTS_STR_EQUAL(tc, TESTSTR, str);
107
108 apr_file_close(filetest);
109 }
110
test_readzero(abts_case * tc,void * data)111 static void test_readzero(abts_case *tc, void *data)
112 {
113 apr_status_t rv;
114 apr_size_t nbytes = 0;
115 char *str = NULL;
116 apr_file_t *filetest;
117
118 rv = apr_file_open(&filetest, FILENAME, APR_FOPEN_READ, APR_OS_DEFAULT, p);
119 APR_ASSERT_SUCCESS(tc, "Opening test file " FILENAME, rv);
120
121 rv = apr_file_read(filetest, str, &nbytes);
122 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
123 ABTS_SIZE_EQUAL(tc, 0, nbytes);
124
125 apr_file_close(filetest);
126 }
127
test_filename(abts_case * tc,void * data)128 static void test_filename(abts_case *tc, void *data)
129 {
130 const char *str;
131 apr_status_t rv;
132 apr_file_t *filetest = NULL;
133
134 rv = apr_file_open(&filetest, FILENAME,
135 APR_FOPEN_READ,
136 APR_UREAD | APR_UWRITE | APR_GREAD, p);
137 APR_ASSERT_SUCCESS(tc, "Opening test file " FILENAME, rv);
138
139 rv = apr_file_name_get(&str, filetest);
140 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
141 ABTS_STR_EQUAL(tc, FILENAME, str);
142
143 apr_file_close(filetest);
144 }
145
test_fileclose(abts_case * tc,void * data)146 static void test_fileclose(abts_case *tc, void *data)
147 {
148 char str;
149 apr_status_t rv;
150 apr_size_t one = 1;
151 apr_file_t *filetest = NULL;
152
153 rv = apr_file_open(&filetest, FILENAME,
154 APR_FOPEN_READ,
155 APR_UREAD | APR_UWRITE | APR_GREAD, p);
156 APR_ASSERT_SUCCESS(tc, "Opening test file " FILENAME, rv);
157
158 rv = apr_file_close(filetest);
159 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
160 /* We just closed the file, so this should fail */
161 rv = apr_file_read(filetest, &str, &one);
162 ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EBADF(rv));
163 }
164
test_file_remove(abts_case * tc,void * data)165 static void test_file_remove(abts_case *tc, void *data)
166 {
167 apr_status_t rv;
168 apr_file_t *filetest = NULL;
169
170 rv = apr_file_remove(FILENAME, p);
171 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
172
173 rv = apr_file_open(&filetest, FILENAME, APR_FOPEN_READ,
174 APR_UREAD | APR_UWRITE | APR_GREAD, p);
175 ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv));
176 }
177
test_open_write(abts_case * tc,void * data)178 static void test_open_write(abts_case *tc, void *data)
179 {
180 apr_status_t rv;
181 apr_file_t *filetest = NULL;
182
183 filetest = NULL;
184 rv = apr_file_open(&filetest, FILENAME,
185 APR_FOPEN_WRITE,
186 APR_UREAD | APR_UWRITE | APR_GREAD, p);
187 ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv));
188 ABTS_PTR_EQUAL(tc, NULL, filetest);
189 }
190
test_open_writecreate(abts_case * tc,void * data)191 static void test_open_writecreate(abts_case *tc, void *data)
192 {
193 apr_status_t rv;
194 apr_file_t *filetest = NULL;
195
196 filetest = NULL;
197 rv = apr_file_open(&filetest, FILENAME,
198 APR_FOPEN_WRITE | APR_FOPEN_CREATE,
199 APR_UREAD | APR_UWRITE | APR_GREAD, p);
200 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
201
202 apr_file_close(filetest);
203 }
204
test_write(abts_case * tc,void * data)205 static void test_write(abts_case *tc, void *data)
206 {
207 apr_status_t rv;
208 apr_size_t bytes = strlen(TESTSTR);
209 apr_file_t *filetest = NULL;
210
211 rv = apr_file_open(&filetest, FILENAME,
212 APR_FOPEN_WRITE | APR_FOPEN_CREATE,
213 APR_UREAD | APR_UWRITE | APR_GREAD, p);
214 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
215
216 rv = apr_file_write(filetest, TESTSTR, &bytes);
217 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
218
219 apr_file_close(filetest);
220 }
221
test_open_readwrite(abts_case * tc,void * data)222 static void test_open_readwrite(abts_case *tc, void *data)
223 {
224 apr_status_t rv;
225 apr_file_t *filetest = NULL;
226
227 filetest = NULL;
228 rv = apr_file_open(&filetest, FILENAME,
229 APR_FOPEN_READ | APR_FOPEN_WRITE,
230 APR_UREAD | APR_UWRITE | APR_GREAD, p);
231 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
232 ABTS_PTR_NOTNULL(tc, filetest);
233
234 apr_file_close(filetest);
235 }
236
test_seek(abts_case * tc,void * data)237 static void test_seek(abts_case *tc, void *data)
238 {
239 apr_status_t rv;
240 apr_off_t offset = 5;
241 apr_size_t nbytes = 256;
242 char *str = apr_pcalloc(p, nbytes + 1);
243 apr_file_t *filetest = NULL;
244
245 rv = apr_file_open(&filetest, FILENAME,
246 APR_FOPEN_READ,
247 APR_UREAD | APR_UWRITE | APR_GREAD, p);
248 APR_ASSERT_SUCCESS(tc, "Open test file " FILENAME, rv);
249
250 rv = apr_file_read(filetest, str, &nbytes);
251 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
252 ABTS_SIZE_EQUAL(tc, strlen(TESTSTR), nbytes);
253 ABTS_STR_EQUAL(tc, TESTSTR, str);
254
255 memset(str, 0, nbytes + 1);
256
257 rv = apr_file_seek(filetest, SEEK_SET, &offset);
258 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
259
260 rv = apr_file_read(filetest, str, &nbytes);
261 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
262 ABTS_SIZE_EQUAL(tc, strlen(TESTSTR) - 5, nbytes);
263 ABTS_STR_EQUAL(tc, TESTSTR + 5, str);
264
265 apr_file_close(filetest);
266
267 /* Test for regression of sign error bug with SEEK_END and
268 buffered files. */
269 rv = apr_file_open(&filetest, FILENAME,
270 APR_FOPEN_READ | APR_FOPEN_BUFFERED,
271 APR_UREAD | APR_UWRITE | APR_GREAD, p);
272 APR_ASSERT_SUCCESS(tc, "Open test file " FILENAME, rv);
273
274 offset = -5;
275 rv = apr_file_seek(filetest, SEEK_END, &offset);
276 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
277 ABTS_SIZE_EQUAL(tc, strlen(TESTSTR) - 5, nbytes);
278
279 memset(str, 0, nbytes + 1);
280 nbytes = 256;
281 rv = apr_file_read(filetest, str, &nbytes);
282 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
283 ABTS_SIZE_EQUAL(tc, 5, nbytes);
284 ABTS_STR_EQUAL(tc, TESTSTR + strlen(TESTSTR) - 5, str);
285
286 apr_file_close(filetest);
287 }
288
test_userdata_set(abts_case * tc,void * data)289 static void test_userdata_set(abts_case *tc, void *data)
290 {
291 apr_status_t rv;
292 apr_file_t *filetest = NULL;
293
294 rv = apr_file_open(&filetest, FILENAME,
295 APR_FOPEN_WRITE,
296 APR_UREAD | APR_UWRITE | APR_GREAD, p);
297 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
298
299 rv = apr_file_data_set(filetest, "This is a test",
300 "test", apr_pool_cleanup_null);
301 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
302 apr_file_close(filetest);
303 }
304
test_userdata_get(abts_case * tc,void * data)305 static void test_userdata_get(abts_case *tc, void *data)
306 {
307 apr_status_t rv;
308 void *udata;
309 char *teststr;
310 apr_file_t *filetest = NULL;
311
312 rv = apr_file_open(&filetest, FILENAME,
313 APR_FOPEN_WRITE,
314 APR_UREAD | APR_UWRITE | APR_GREAD, p);
315 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
316
317 rv = apr_file_data_set(filetest, "This is a test",
318 "test", apr_pool_cleanup_null);
319 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
320
321 rv = apr_file_data_get(&udata, "test", filetest);
322 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
323 teststr = udata;
324 ABTS_STR_EQUAL(tc, "This is a test", teststr);
325
326 apr_file_close(filetest);
327 }
328
test_userdata_getnokey(abts_case * tc,void * data)329 static void test_userdata_getnokey(abts_case *tc, void *data)
330 {
331 apr_status_t rv;
332 void *teststr;
333 apr_file_t *filetest = NULL;
334
335 rv = apr_file_open(&filetest, FILENAME,
336 APR_FOPEN_WRITE,
337 APR_UREAD | APR_UWRITE | APR_GREAD, p);
338 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
339
340 rv = apr_file_data_get(&teststr, "nokey", filetest);
341 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
342 ABTS_PTR_EQUAL(tc, NULL, teststr);
343 apr_file_close(filetest);
344 }
345
test_buffer_set_get(abts_case * tc,void * data)346 static void test_buffer_set_get(abts_case *tc, void *data)
347 {
348 apr_status_t rv;
349 apr_size_t bufsize;
350 apr_file_t *filetest = NULL;
351 char * buffer;
352
353 rv = apr_file_open(&filetest, FILENAME,
354 APR_FOPEN_WRITE | APR_FOPEN_BUFFERED,
355 APR_UREAD | APR_UWRITE | APR_GREAD, p);
356 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
357
358 bufsize = apr_file_buffer_size_get(filetest);
359 ABTS_SIZE_EQUAL(tc, APR_BUFFERSIZE, bufsize);
360
361 buffer = apr_pcalloc(p, 10240);
362 rv = apr_file_buffer_set(filetest, buffer, 10240);
363 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
364
365 bufsize = apr_file_buffer_size_get(filetest);
366 ABTS_SIZE_EQUAL(tc, 10240, bufsize);
367
368 rv = apr_file_buffer_set(filetest, buffer, 12);
369 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
370
371 bufsize = apr_file_buffer_size_get(filetest);
372 ABTS_SIZE_EQUAL(tc, 12, bufsize);
373
374 apr_file_close(filetest);
375 }
test_getc(abts_case * tc,void * data)376 static void test_getc(abts_case *tc, void *data)
377 {
378 apr_file_t *f = NULL;
379 apr_status_t rv;
380 char ch;
381
382 rv = apr_file_open(&f, FILENAME, APR_FOPEN_READ, 0, p);
383 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
384
385 apr_file_getc(&ch, f);
386 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
387 ABTS_INT_EQUAL(tc, (int)TESTSTR[0], (int)ch);
388 apr_file_close(f);
389 }
390
test_ungetc(abts_case * tc,void * data)391 static void test_ungetc(abts_case *tc, void *data)
392 {
393 apr_file_t *f = NULL;
394 apr_status_t rv;
395 char ch;
396
397 rv = apr_file_open(&f, FILENAME, APR_FOPEN_READ, 0, p);
398 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
399
400 apr_file_getc(&ch, f);
401 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
402 ABTS_INT_EQUAL(tc, (int)TESTSTR[0], (int)ch);
403
404 apr_file_ungetc('X', f);
405 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
406
407 apr_file_getc(&ch, f);
408 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
409 ABTS_INT_EQUAL(tc, 'X', (int)ch);
410
411 apr_file_close(f);
412 }
413
test_gets(abts_case * tc,void * data)414 static void test_gets(abts_case *tc, void *data)
415 {
416 apr_file_t *f = NULL;
417 apr_status_t rv;
418 char *str = apr_palloc(p, 256);
419
420 rv = apr_file_open(&f, FILENAME, APR_FOPEN_READ, 0, p);
421 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
422
423 rv = apr_file_gets(str, 256, f);
424 /* Only one line in the test file, so APR will encounter EOF on the first
425 * call to gets, but we should get APR_SUCCESS on this call and
426 * APR_EOF on the next.
427 */
428 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
429 ABTS_STR_EQUAL(tc, TESTSTR, str);
430 rv = apr_file_gets(str, 256, f);
431 ABTS_INT_EQUAL(tc, APR_EOF, rv);
432 ABTS_STR_EQUAL(tc, "", str);
433 apr_file_close(f);
434 }
435
test_gets_buffered(abts_case * tc,void * data)436 static void test_gets_buffered(abts_case *tc, void *data)
437 {
438 apr_file_t *f = NULL;
439 apr_status_t rv;
440 char *str = apr_palloc(p, 256);
441
442 /* This will deadlock gets before the r524355 fix. */
443 rv = apr_file_open(&f, FILENAME, APR_FOPEN_READ|APR_FOPEN_BUFFERED|APR_FOPEN_XTHREAD, 0, p);
444 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
445
446 rv = apr_file_gets(str, 256, f);
447 /* Only one line in the test file, so APR will encounter EOF on the first
448 * call to gets, but we should get APR_SUCCESS on this call and
449 * APR_EOF on the next.
450 */
451 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
452 ABTS_STR_EQUAL(tc, TESTSTR, str);
453 rv = apr_file_gets(str, 256, f);
454 ABTS_INT_EQUAL(tc, APR_EOF, rv);
455 ABTS_STR_EQUAL(tc, "", str);
456 apr_file_close(f);
457 }
458
test_bigread(abts_case * tc,void * data)459 static void test_bigread(abts_case *tc, void *data)
460 {
461 apr_file_t *f = NULL;
462 apr_status_t rv;
463 char buf[APR_BUFFERSIZE * 2];
464 apr_size_t nbytes;
465
466 /* Create a test file with known content.
467 */
468 rv = apr_file_open(&f, "data/created_file",
469 APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_TRUNCATE,
470 APR_UREAD | APR_UWRITE, p);
471 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
472
473 nbytes = APR_BUFFERSIZE;
474 memset(buf, 0xFE, nbytes);
475
476 rv = apr_file_write(f, buf, &nbytes);
477 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
478 ABTS_SIZE_EQUAL(tc, APR_BUFFERSIZE, nbytes);
479
480 rv = apr_file_close(f);
481 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
482
483 f = NULL;
484 rv = apr_file_open(&f, "data/created_file", APR_FOPEN_READ, 0, p);
485 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
486
487 nbytes = sizeof buf;
488 rv = apr_file_read(f, buf, &nbytes);
489 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
490 ABTS_SIZE_EQUAL(tc, APR_BUFFERSIZE, nbytes);
491
492 rv = apr_file_close(f);
493 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
494
495 rv = apr_file_remove("data/created_file", p);
496 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
497 }
498
499 /* This is a horrible name for this function. We are testing APR, not how
500 * Apache uses APR. And, this function tests _way_ too much stuff.
501 */
test_mod_neg(abts_case * tc,void * data)502 static void test_mod_neg(abts_case *tc, void *data)
503 {
504 apr_status_t rv;
505 apr_file_t *f;
506 const char *s;
507 int i;
508 apr_size_t nbytes;
509 char buf[8192];
510 apr_off_t cur;
511 const char *fname = "data/modneg.dat";
512
513 rv = apr_file_open(&f, fname,
514 APR_FOPEN_CREATE | APR_FOPEN_WRITE, APR_UREAD | APR_UWRITE, p);
515 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
516
517 s = "body56789\n";
518 nbytes = strlen(s);
519 rv = apr_file_write(f, s, &nbytes);
520 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
521 ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
522
523 for (i = 0; i < 7980; i++) {
524 s = "0";
525 nbytes = strlen(s);
526 rv = apr_file_write(f, s, &nbytes);
527 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
528 ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
529 }
530
531 s = "end456789\n";
532 nbytes = strlen(s);
533 rv = apr_file_write(f, s, &nbytes);
534 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
535 ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
536
537 for (i = 0; i < 10000; i++) {
538 s = "1";
539 nbytes = strlen(s);
540 rv = apr_file_write(f, s, &nbytes);
541 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
542 ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
543 }
544
545 rv = apr_file_close(f);
546 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
547
548 rv = apr_file_open(&f, fname, APR_FOPEN_READ, 0, p);
549 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
550
551 rv = apr_file_gets(buf, 11, f);
552 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
553 ABTS_STR_EQUAL(tc, "body56789\n", buf);
554
555 cur = 0;
556 rv = apr_file_seek(f, APR_CUR, &cur);
557 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
558 ABTS_ASSERT(tc, "File Pointer Mismatch, expected 10", cur == 10);
559
560 nbytes = sizeof(buf);
561 rv = apr_file_read(f, buf, &nbytes);
562 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
563 ABTS_SIZE_EQUAL(tc, nbytes, sizeof(buf));
564
565 cur = -((apr_off_t)nbytes - 7980);
566 rv = apr_file_seek(f, APR_CUR, &cur);
567 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
568 ABTS_ASSERT(tc, "File Pointer Mismatch, expected 7990", cur == 7990);
569
570 rv = apr_file_gets(buf, 11, f);
571 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
572 ABTS_STR_EQUAL(tc, "end456789\n", buf);
573
574 rv = apr_file_close(f);
575 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
576
577 rv = apr_file_remove(fname, p);
578 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
579 }
580
581 /* Test that the contents of file FNAME are equal to data EXPECT of
582 * length EXPECTLEN. */
file_contents_equal(abts_case * tc,const char * fname,const void * expect,apr_size_t expectlen)583 static void file_contents_equal(abts_case *tc,
584 const char *fname,
585 const void *expect,
586 apr_size_t expectlen)
587 {
588 void *actual = apr_palloc(p, expectlen);
589 apr_file_t *f;
590
591 APR_ASSERT_SUCCESS(tc, "open file",
592 apr_file_open(&f, fname, APR_FOPEN_READ|APR_FOPEN_BUFFERED,
593 0, p));
594 APR_ASSERT_SUCCESS(tc, "read from file",
595 apr_file_read_full(f, actual, expectlen, NULL));
596
597 ABTS_ASSERT(tc, "matched expected file contents",
598 memcmp(expect, actual, expectlen) == 0);
599
600 APR_ASSERT_SUCCESS(tc, "close file", apr_file_close(f));
601 }
602
603 #define LINE1 "this is a line of text\n"
604 #define LINE2 "this is a second line of text\n"
605
test_puts(abts_case * tc,void * data)606 static void test_puts(abts_case *tc, void *data)
607 {
608 apr_file_t *f;
609 const char *fname = "data/testputs.txt";
610
611 APR_ASSERT_SUCCESS(tc, "open file for writing",
612 apr_file_open(&f, fname,
613 APR_FOPEN_WRITE|APR_FOPEN_CREATE|APR_FOPEN_TRUNCATE,
614 APR_OS_DEFAULT, p));
615
616 APR_ASSERT_SUCCESS(tc, "write line to file",
617 apr_file_puts(LINE1, f));
618 APR_ASSERT_SUCCESS(tc, "write second line to file",
619 apr_file_puts(LINE2, f));
620
621 APR_ASSERT_SUCCESS(tc, "close for writing",
622 apr_file_close(f));
623
624 file_contents_equal(tc, fname, LINE1 LINE2, strlen(LINE1 LINE2));
625 }
626
test_writev(abts_case * tc,void * data)627 static void test_writev(abts_case *tc, void *data)
628 {
629 apr_file_t *f;
630 apr_size_t nbytes;
631 struct iovec vec[5];
632 const char *fname = "data/testwritev.txt";
633
634 APR_ASSERT_SUCCESS(tc, "open file for writing",
635 apr_file_open(&f, fname,
636 APR_FOPEN_WRITE|APR_FOPEN_CREATE|APR_FOPEN_TRUNCATE,
637 APR_OS_DEFAULT, p));
638
639 vec[0].iov_base = LINE1;
640 vec[0].iov_len = strlen(LINE1);
641
642 APR_ASSERT_SUCCESS(tc, "writev of size 1 to file",
643 apr_file_writev(f, vec, 1, &nbytes));
644
645 file_contents_equal(tc, fname, LINE1, strlen(LINE1));
646
647 vec[0].iov_base = LINE1;
648 vec[0].iov_len = strlen(LINE1);
649 vec[1].iov_base = LINE2;
650 vec[1].iov_len = strlen(LINE2);
651 vec[2].iov_base = LINE1;
652 vec[2].iov_len = strlen(LINE1);
653 vec[3].iov_base = LINE1;
654 vec[3].iov_len = strlen(LINE1);
655 vec[4].iov_base = LINE2;
656 vec[4].iov_len = strlen(LINE2);
657
658 APR_ASSERT_SUCCESS(tc, "writev of size 5 to file",
659 apr_file_writev(f, vec, 5, &nbytes));
660
661 APR_ASSERT_SUCCESS(tc, "close for writing",
662 apr_file_close(f));
663
664 file_contents_equal(tc, fname, LINE1 LINE1 LINE2 LINE1 LINE1 LINE2,
665 strlen(LINE1)*4 + strlen(LINE2)*2);
666
667 }
668
test_writev_full(abts_case * tc,void * data)669 static void test_writev_full(abts_case *tc, void *data)
670 {
671 apr_file_t *f;
672 apr_size_t nbytes;
673 struct iovec vec[5];
674 const char *fname = "data/testwritev_full.txt";
675
676 APR_ASSERT_SUCCESS(tc, "open file for writing",
677 apr_file_open(&f, fname,
678 APR_FOPEN_WRITE|APR_FOPEN_CREATE|APR_FOPEN_TRUNCATE,
679 APR_OS_DEFAULT, p));
680
681 vec[0].iov_base = LINE1;
682 vec[0].iov_len = strlen(LINE1);
683 vec[1].iov_base = LINE2;
684 vec[1].iov_len = strlen(LINE2);
685 vec[2].iov_base = LINE1;
686 vec[2].iov_len = strlen(LINE1);
687 vec[3].iov_base = LINE1;
688 vec[3].iov_len = strlen(LINE1);
689 vec[4].iov_base = LINE2;
690 vec[4].iov_len = strlen(LINE2);
691
692 APR_ASSERT_SUCCESS(tc, "writev_full of size 5 to file",
693 apr_file_writev_full(f, vec, 5, &nbytes));
694
695 ABTS_SIZE_EQUAL(tc, strlen(LINE1)*3 + strlen(LINE2)*2, nbytes);
696
697 APR_ASSERT_SUCCESS(tc, "close for writing",
698 apr_file_close(f));
699
700 file_contents_equal(tc, fname, LINE1 LINE2 LINE1 LINE1 LINE2,
701 strlen(LINE1)*3 + strlen(LINE2)*2);
702
703 }
704
test_writev_buffered(abts_case * tc,void * data)705 static void test_writev_buffered(abts_case *tc, void *data)
706 {
707 apr_file_t *f;
708 apr_size_t nbytes;
709 struct iovec vec[2];
710 const char *fname = "data/testwritev_buffered.dat";
711
712 APR_ASSERT_SUCCESS(tc, "open file for writing",
713 apr_file_open(&f, fname,
714 APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE |
715 APR_FOPEN_BUFFERED, APR_OS_DEFAULT, p));
716
717 nbytes = strlen(TESTSTR);
718 APR_ASSERT_SUCCESS(tc, "buffered write",
719 apr_file_write(f, TESTSTR, &nbytes));
720
721 vec[0].iov_base = LINE1;
722 vec[0].iov_len = strlen(LINE1);
723 vec[1].iov_base = LINE2;
724 vec[1].iov_len = strlen(LINE2);
725
726 APR_ASSERT_SUCCESS(tc, "writev of size 2 to file",
727 apr_file_writev(f, vec, 2, &nbytes));
728
729 APR_ASSERT_SUCCESS(tc, "close for writing",
730 apr_file_close(f));
731
732 file_contents_equal(tc, fname, TESTSTR LINE1 LINE2,
733 strlen(TESTSTR) + strlen(LINE1) + strlen(LINE2));
734 }
735
test_writev_buffered_seek(abts_case * tc,void * data)736 static void test_writev_buffered_seek(abts_case *tc, void *data)
737 {
738 apr_file_t *f;
739 apr_status_t rv;
740 apr_off_t off = 0;
741 struct iovec vec[3];
742 apr_size_t nbytes = strlen(TESTSTR);
743 char *str = apr_pcalloc(p, nbytes+1);
744 const char *fname = "data/testwritev_buffered.dat";
745
746 APR_ASSERT_SUCCESS(tc, "open file for writing",
747 apr_file_open(&f, fname,
748 APR_FOPEN_WRITE | APR_FOPEN_READ | APR_FOPEN_BUFFERED,
749 APR_OS_DEFAULT, p));
750
751 rv = apr_file_read(f, str, &nbytes);
752 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
753 ABTS_STR_EQUAL(tc, TESTSTR, str);
754 APR_ASSERT_SUCCESS(tc, "buffered seek", apr_file_seek(f, APR_SET, &off));
755
756 vec[0].iov_base = LINE1;
757 vec[0].iov_len = strlen(LINE1);
758 vec[1].iov_base = LINE2;
759 vec[1].iov_len = strlen(LINE2);
760 vec[2].iov_base = TESTSTR;
761 vec[2].iov_len = strlen(TESTSTR);
762
763 APR_ASSERT_SUCCESS(tc, "writev of size 2 to file",
764 apr_file_writev(f, vec, 3, &nbytes));
765
766 APR_ASSERT_SUCCESS(tc, "close for writing",
767 apr_file_close(f));
768
769 file_contents_equal(tc, fname, LINE1 LINE2 TESTSTR,
770 strlen(LINE1) + strlen(LINE2) + strlen(TESTSTR));
771
772 APR_ASSERT_SUCCESS(tc, "remove file", apr_file_remove(fname, p));
773 }
774
test_truncate(abts_case * tc,void * data)775 static void test_truncate(abts_case *tc, void *data)
776 {
777 apr_status_t rv;
778 apr_file_t *f;
779 const char *fname = "data/testtruncate.dat";
780 const char *s;
781 apr_size_t nbytes;
782 apr_finfo_t finfo;
783
784 apr_file_remove(fname, p);
785
786 rv = apr_file_open(&f, fname,
787 APR_FOPEN_CREATE | APR_FOPEN_WRITE, APR_UREAD | APR_UWRITE, p);
788 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
789
790 s = "some data";
791 nbytes = strlen(s);
792 rv = apr_file_write(f, s, &nbytes);
793 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
794 ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
795
796 rv = apr_file_close(f);
797 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
798
799 rv = apr_file_open(&f, fname,
800 APR_FOPEN_TRUNCATE | APR_FOPEN_WRITE, APR_UREAD | APR_UWRITE, p);
801 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
802
803 rv = apr_file_close(f);
804 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
805
806 rv = apr_stat(&finfo, fname, APR_FINFO_SIZE, p);
807 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
808 ABTS_ASSERT(tc, "File size mismatch, expected 0 (empty)", finfo.size == 0);
809
810 rv = apr_file_remove(fname, p);
811 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
812 }
813
test_bigfprintf(abts_case * tc,void * data)814 static void test_bigfprintf(abts_case *tc, void *data)
815 {
816 apr_file_t *f;
817 const char *fname = "data/testbigfprintf.dat";
818 char *to_write;
819 int i;
820
821 apr_file_remove(fname, p);
822
823 APR_ASSERT_SUCCESS(tc, "open test file",
824 apr_file_open(&f, fname,
825 APR_FOPEN_CREATE|APR_FOPEN_WRITE,
826 APR_UREAD|APR_UWRITE, p));
827
828
829 to_write = malloc(HUGE_STRING_LEN + 3);
830
831 for (i = 0; i < HUGE_STRING_LEN + 1; ++i)
832 to_write[i] = 'A' + i%26;
833
834 strcpy(to_write + HUGE_STRING_LEN, "42");
835
836 i = apr_file_printf(f, "%s", to_write);
837 ABTS_INT_EQUAL(tc, HUGE_STRING_LEN + 2, i);
838
839 apr_file_close(f);
840
841 file_contents_equal(tc, fname, to_write, HUGE_STRING_LEN + 2);
842
843 free(to_write);
844 }
845
test_fail_write_flush(abts_case * tc,void * data)846 static void test_fail_write_flush(abts_case *tc, void *data)
847 {
848 apr_file_t *f;
849 const char *fname = "data/testflush.dat";
850 apr_status_t rv;
851 char buf[APR_BUFFERSIZE];
852 int n;
853
854 apr_file_remove(fname, p);
855
856 APR_ASSERT_SUCCESS(tc, "open test file",
857 apr_file_open(&f, fname,
858 APR_FOPEN_CREATE|APR_FOPEN_READ|APR_FOPEN_BUFFERED,
859 APR_UREAD|APR_UWRITE, p));
860
861 memset(buf, 'A', sizeof buf);
862
863 /* Try three writes. One of these should fail when it exceeds the
864 * internal buffer and actually tries to write to the file, which
865 * was opened read-only and hence should be unwritable. */
866 for (n = 0, rv = APR_SUCCESS; n < 4 && rv == APR_SUCCESS; n++) {
867 apr_size_t bytes = sizeof buf;
868 rv = apr_file_write(f, buf, &bytes);
869 }
870
871 ABTS_ASSERT(tc, "failed to write to read-only buffered fd",
872 rv != APR_SUCCESS);
873
874 apr_file_close(f);
875 }
876
test_fail_read_flush(abts_case * tc,void * data)877 static void test_fail_read_flush(abts_case *tc, void *data)
878 {
879 apr_file_t *f;
880 const char *fname = "data/testflush.dat";
881 apr_status_t rv;
882 char buf[2];
883
884 apr_file_remove(fname, p);
885
886 APR_ASSERT_SUCCESS(tc, "open test file",
887 apr_file_open(&f, fname,
888 APR_FOPEN_CREATE|APR_FOPEN_READ|APR_FOPEN_BUFFERED,
889 APR_UREAD|APR_UWRITE, p));
890
891 /* this write should be buffered. */
892 APR_ASSERT_SUCCESS(tc, "buffered write should succeed",
893 apr_file_puts("hello", f));
894
895 /* Now, trying a read should fail since the write must be flushed,
896 * and should fail with something other than EOF since the file is
897 * opened read-only. */
898 rv = apr_file_read_full(f, buf, 2, NULL);
899
900 ABTS_ASSERT(tc, "read should flush buffered write and fail",
901 rv != APR_SUCCESS && rv != APR_EOF);
902
903 /* Likewise for gets */
904 rv = apr_file_gets(buf, 2, f);
905
906 ABTS_ASSERT(tc, "gets should flush buffered write and fail",
907 rv != APR_SUCCESS && rv != APR_EOF);
908
909 /* Likewise for seek. */
910 {
911 apr_off_t offset = 0;
912
913 rv = apr_file_seek(f, APR_SET, &offset);
914 }
915
916 ABTS_ASSERT(tc, "seek should flush buffered write and fail",
917 rv != APR_SUCCESS && rv != APR_EOF);
918
919 apr_file_close(f);
920 }
921
test_xthread(abts_case * tc,void * data)922 static void test_xthread(abts_case *tc, void *data)
923 {
924 apr_file_t *f;
925 const char *fname = "data/testxthread.dat";
926 apr_status_t rv;
927 apr_int32_t flags = APR_FOPEN_CREATE|APR_FOPEN_READ|APR_FOPEN_WRITE|APR_FOPEN_APPEND|APR_FOPEN_XTHREAD;
928 char buf[128] = { 0 };
929
930 /* Test for bug 38438, opening file with append + xthread and seeking to
931 the end of the file resulted in writes going to the beginning not the
932 end. */
933
934 apr_file_remove(fname, p);
935
936 APR_ASSERT_SUCCESS(tc, "open test file",
937 apr_file_open(&f, fname, flags,
938 APR_UREAD|APR_UWRITE, p));
939
940 APR_ASSERT_SUCCESS(tc, "write should succeed",
941 apr_file_puts("hello", f));
942
943 apr_file_close(f);
944
945 APR_ASSERT_SUCCESS(tc, "open test file",
946 apr_file_open(&f, fname, flags,
947 APR_UREAD|APR_UWRITE, p));
948
949 /* Seek to the end. */
950 {
951 apr_off_t offset = 0;
952
953 rv = apr_file_seek(f, APR_END, &offset);
954 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
955 }
956
957 APR_ASSERT_SUCCESS(tc, "more writes should succeed",
958 apr_file_puts("world", f));
959
960 /* Back to the beginning. */
961 {
962 apr_off_t offset = 0;
963
964 rv = apr_file_seek(f, APR_SET, &offset);
965 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
966 }
967
968 apr_file_read_full(f, buf, sizeof(buf), NULL);
969
970 ABTS_STR_EQUAL(tc, "helloworld", buf);
971
972 apr_file_close(f);
973 }
974
testfile(abts_suite * suite)975 abts_suite *testfile(abts_suite *suite)
976 {
977 suite = ADD_SUITE(suite)
978
979 abts_run_test(suite, test_open_noreadwrite, NULL);
980 abts_run_test(suite, test_open_excl, NULL);
981 abts_run_test(suite, test_open_read, NULL);
982 abts_run_test(suite, test_open_readwrite, NULL);
983 abts_run_test(suite, link_existing, NULL);
984 abts_run_test(suite, link_nonexisting, NULL);
985 abts_run_test(suite, test_read, NULL);
986 abts_run_test(suite, test_readzero, NULL);
987 abts_run_test(suite, test_seek, NULL);
988 abts_run_test(suite, test_filename, NULL);
989 abts_run_test(suite, test_fileclose, NULL);
990 abts_run_test(suite, test_file_remove, NULL);
991 abts_run_test(suite, test_open_write, NULL);
992 abts_run_test(suite, test_open_writecreate, NULL);
993 abts_run_test(suite, test_write, NULL);
994 abts_run_test(suite, test_userdata_set, NULL);
995 abts_run_test(suite, test_userdata_get, NULL);
996 abts_run_test(suite, test_userdata_getnokey, NULL);
997 abts_run_test(suite, test_getc, NULL);
998 abts_run_test(suite, test_ungetc, NULL);
999 abts_run_test(suite, test_gets, NULL);
1000 abts_run_test(suite, test_gets_buffered, NULL);
1001 abts_run_test(suite, test_puts, NULL);
1002 abts_run_test(suite, test_writev, NULL);
1003 abts_run_test(suite, test_writev_full, NULL);
1004 abts_run_test(suite, test_writev_buffered, NULL);
1005 abts_run_test(suite, test_writev_buffered_seek, NULL);
1006 abts_run_test(suite, test_bigread, NULL);
1007 abts_run_test(suite, test_mod_neg, NULL);
1008 abts_run_test(suite, test_truncate, NULL);
1009 abts_run_test(suite, test_bigfprintf, NULL);
1010 abts_run_test(suite, test_fail_write_flush, NULL);
1011 abts_run_test(suite, test_fail_read_flush, NULL);
1012 abts_run_test(suite, test_buffer_set_get, NULL);
1013 abts_run_test(suite, test_xthread, NULL);
1014
1015 return suite;
1016 }
1017
1018