/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* .
*/
#include
#include
#include
#include
#include "apr_file_io.h"
#include "apr_network_io.h"
#include "apr_errno.h"
#include "apr_general.h"
#include "apr_lib.h"
#ifdef BEOS
#include
#endif
int test_filedel(apr_pool_t *);
int testdirs(apr_pool_t *);
static void test_read(apr_pool_t *);
int main(void)
{
apr_pool_t *context;
apr_pool_t *cont2;
apr_file_t *thefile = NULL;
apr_socket_t *testsock = NULL;
apr_pollfd_t *sdset = NULL;
apr_status_t status = 0;
apr_int32_t flag = APR_READ | APR_WRITE | APR_CREATE;
apr_size_t nbytes = 0;
apr_int32_t rv;
apr_off_t zer = 0;
char *buf;
char *str;
char *filename = "test.fil";
char *teststr;
if (apr_initialize() != APR_SUCCESS) {
fprintf(stderr, "Couldn't initialize.");
exit(-1);
}
atexit(apr_terminate);
if (apr_create_pool(&context, NULL) != APR_SUCCESS) {
fprintf(stderr, "Couldn't allocate context.");
exit(-1);
}
if (apr_create_pool(&cont2, context) != APR_SUCCESS) {
fprintf(stderr, "Couldn't allocate context.");
exit(-1);
}
fprintf(stdout, "Testing file functions.\n");
fprintf(stdout, "\tOpening file.......");
if (apr_open(&thefile, filename, flag, APR_UREAD | APR_UWRITE | APR_GREAD, context) != APR_SUCCESS) {
perror("Didn't open file");
exit(-1);
}
else {
fprintf(stdout, "OK\n");
}
fprintf(stdout, "\tChecking file.......");
if (thefile == NULL) {
fprintf(stderr, "Bad file des\n");
exit(-1);
}
apr_get_filename(&str, thefile);
if (strcmp(str, filename) != 0) {
fprintf(stderr, "wrong filename\n");
exit(-1);
}
else {
fprintf(stdout, "OK\n");
}
fprintf(stdout, "\tWriting to file.......");
nbytes = strlen("this is a test");
if (apr_write(thefile, "this is a test", &nbytes) != APR_SUCCESS) {
perror("something's wrong");
exit(-1);
}
if (nbytes != strlen("this is a test")) {
fprintf(stderr, "didn't write properly.\n");
exit(-1);
}
else {
fprintf(stdout, "OK\n");
}
fprintf(stdout, "\tMoving to start of file.......");
zer = 0;
if (apr_seek(thefile, SEEK_SET, &zer) != 0) {
perror("couldn't seek to beginning of file.");
exit(-1);
}
else {
fprintf(stdout, "OK\n");
}
#if APR_FILES_AS_SOCKETS
fprintf(stdout, "\tThis platform supports files_like_sockets\n");
fprintf(stdout, "\t\tMaking file look like a socket.......");
if (apr_socket_from_file(&testsock, thefile) != APR_SUCCESS) {
perror("Something went wrong");
exit(-1);
}
fprintf(stdout, "OK\n");
fprintf(stdout, "\t\tChecking for incoming data.......");
apr_setup_poll(&sdset, 1, context);
apr_add_poll_socket(sdset, testsock, APR_POLLIN);
rv = 1;
if (apr_poll(sdset, &rv, -1) != APR_SUCCESS) {
fprintf(stderr, "Select caused an error\n");
exit(-1);
}
else if (rv == 0) {
fprintf(stderr, "I should not return until rv == 1\n");
exit(-1);
}
fprintf(stdout, "OK\n");
#endif
fprintf(stdout, "\tReading from the file.......");
nbytes = strlen("this is a test");
buf = (char *)apr_palloc(context, nbytes + 1);
if (apr_read(thefile, buf, &nbytes) != APR_SUCCESS) {
perror("something's wrong");
exit(-1);
}
if (nbytes != strlen("this is a test")) {
fprintf(stderr, "didn't read properly.\n");
exit(-1);
}
else {
fprintf(stdout, "OK\n");
}
fprintf(stdout, "\tAdding user data to the file.......");
status = apr_set_filedata(thefile, "This is a test", "test", apr_null_cleanup);
if (status != APR_SUCCESS) {
fprintf(stderr, "Couldn't add the data\n");
exit(-1);
}
else {
fprintf(stdout, "OK\n");
}
fprintf(stdout, "\tGetting user data from the file.......");
status = apr_get_filedata((void **)&teststr, "test", thefile);
if (status != APR_SUCCESS || strcmp(teststr, "This is a test")) {
fprintf(stderr, "Couldn't get the data\n");
exit(-1);
}
else {
fprintf(stdout, "OK\n");
}
fprintf(stdout, "\tClosing File.......");
status = apr_close(thefile);
if (status != APR_SUCCESS) {
fprintf(stderr, "Couldn't close the file\n");
exit(-1);
}
else {
fprintf(stdout, "OK\n");
}
fprintf(stdout, "\tDeleting file.......");
status = apr_remove_file(filename, context);
if (status != APR_SUCCESS) {
fprintf(stderr, "Couldn't delete the file\n");
exit(-1);
}
else {
fprintf(stdout, "OK\n");
}
fprintf(stdout, "\tMaking sure it's gone.......");
status = apr_open(&thefile, filename, APR_READ, APR_UREAD | APR_UWRITE | APR_GREAD, context);
if (status == APR_SUCCESS) {
fprintf(stderr, "I could open the file for some reason?\n");
exit(-1);
}
else {
fprintf(stdout, "OK\n");
}
testdirs(context);
test_filedel(context);
test_read(context);
return 1;
}
int test_filedel(apr_pool_t *context)
{
apr_file_t *thefile = NULL;
apr_int32_t flag = APR_READ | APR_WRITE | APR_CREATE;
apr_status_t stat;
stat = apr_open(&thefile, "testdel", flag, APR_UREAD | APR_UWRITE | APR_GREAD, context);
if (stat != APR_SUCCESS) {
return stat;
}
if ((stat = apr_close(thefile)) != APR_SUCCESS) {
return stat;
}
if ((stat = apr_remove_file("testdel", context)) != APR_SUCCESS) {
return stat;
}
stat = apr_open(&thefile, "testdel", APR_READ, APR_UREAD | APR_UWRITE | APR_GREAD, context);
if (stat == APR_SUCCESS) {
return stat;
}
return APR_SUCCESS;
}
int testdirs(apr_pool_t *context)
{
apr_dir_t *temp;
apr_file_t *file = NULL;
apr_size_t bytes;
apr_filetype_e type;
char *fname;
fprintf(stdout, "Testing Directory functions.\n");
fprintf(stdout, "\tMakeing Directory.......");
if (apr_make_dir("testdir", APR_UREAD | APR_UWRITE | APR_UEXECUTE | APR_GREAD | APR_GWRITE | APR_GEXECUTE | APR_WREAD | APR_WWRITE | APR_WEXECUTE, context) != APR_SUCCESS) {
fprintf(stderr, "Could not create directory\n");
return -1;
}
else {
fprintf(stdout, "OK\n");
}
if (apr_open(&file, "testdir/testfile", APR_READ | APR_WRITE | APR_CREATE, APR_UREAD | APR_UWRITE | APR_UEXECUTE, context) != APR_SUCCESS) {;
return -1;
}
bytes = strlen("Another test!!!");
apr_write(file, "Another test!!", &bytes);
apr_close(file);
fprintf(stdout, "\tOpening Directory.......");
if (apr_dir_open(&temp, "testdir", context) != APR_SUCCESS) {
fprintf(stderr, "Could not open directory\n");
return -1;
}
else {
fprintf(stdout, "OK\n");
}
fprintf(stdout, "\tReading Directory.......");
if ((apr_readdir(temp)) != APR_SUCCESS) {
fprintf(stderr, "Could not read directory\n");
return -1;
}
else {
fprintf(stdout, "OK\n");
}
fprintf(stdout, "\tGetting Information about the file.......\n");
fprintf(stdout, "\t\tFile name.......");
do {
/* Because I want the file I created, I am skipping the "." and ".."
* files that are here.
*/
if (apr_readdir(temp) != APR_SUCCESS) {
fprintf(stderr, "Error reading directory testdir");
return -1;
}
apr_get_dir_filename(&fname, temp);
} while (fname[0] == '.');
if (strcmp(fname, "testfile")) {
fprintf(stderr, "Got wrong file name %s\n", fname);
return -1;
}
fprintf(stdout, "OK\n");
fprintf(stdout, "\t\tFile type.......");
apr_dir_entry_ftype(&type, temp);
if (type != APR_REG) {
fprintf(stderr, "Got wrong file type\n");
return -1;
}
fprintf(stdout, "OK\n");
fprintf(stdout, "\t\tFile size.......");
apr_dir_entry_size(&bytes, temp);
if (bytes != strlen("Another test!!!")) {
fprintf(stderr, "Got wrong file size %d\n", bytes);
return -1;
}
fprintf(stdout, "OK\n");
fprintf(stdout, "\tRewinding directory.......");
apr_rewinddir(temp);
fprintf(stdout, "OK\n");
fprintf(stdout, "\tClosing Directory.......");
if (apr_closedir(temp) != APR_SUCCESS) {
fprintf(stderr, "Could not close directory\n");
return -1;
}
else {
fprintf(stdout, "OK\n");
}
fprintf(stdout, "\tRemoving file from directory.......");
if (apr_remove_file("testdir/testfile", context) != APR_SUCCESS) {
fprintf(stderr, "Could not remove file\n");
return -1;
}
else {
fprintf(stdout, "OK\n");
}
fprintf(stdout, "\tRemoving Directory.......");
if (apr_remove_dir("testdir", context) != APR_SUCCESS) {
fprintf(stderr, "Could not remove directory\n");
return -1;
}
else {
fprintf(stdout, "OK\n");
}
return 1;
}
#define TESTREAD_BLKSIZE 1024
#define APR_BUFFERSIZE 4096 /* This should match APR's buffer size. */
static void create_testread(apr_pool_t *p, const char *fname)
{
apr_file_t *f = NULL;
apr_status_t rv;
char buf[TESTREAD_BLKSIZE];
apr_size_t nbytes;
/* Create a test file with known content.
*/
rv = apr_open(&f, fname, APR_CREATE | APR_WRITE | APR_TRUNCATE, APR_UREAD | APR_UWRITE, p);
if (rv) {
fprintf(stderr, "apr_open()->%d/%s\n",
rv, apr_strerror(rv, buf, sizeof buf));
exit(1);
}
nbytes = 4;
rv = apr_write(f, "abc\n", &nbytes);
assert(!rv && nbytes == 4);
memset(buf, 'a', sizeof buf);
nbytes = sizeof buf;
rv = apr_write(f, buf, &nbytes);
assert(!rv && nbytes == sizeof buf);
nbytes = 2;
rv = apr_write(f, "\n\n", &nbytes);
assert(!rv && nbytes == 2);
rv = apr_close(f);
assert(!rv);
}
static char read_one(apr_file_t *f, int expected)
{
char bytes[3];
apr_status_t rv;
static int counter = 0;
apr_size_t nbytes;
counter += 1;
bytes[0] = bytes[2] = 0x01;
if (counter % 2) {
rv = apr_getc(bytes + 1, f);
}
else {
nbytes = 1;
rv = apr_read(f, bytes + 1, &nbytes);
assert(nbytes == 1);
}
assert(!rv);
assert(bytes[0] == 0x01 && bytes[2] == 0x01);
if (expected != -1) {
assert(bytes[1] == expected);
}
return bytes[1];
}
static void test_read_guts(apr_pool_t *p, const char *fname, apr_int32_t extra_flags)
{
apr_file_t *f = NULL;
apr_status_t rv;
apr_size_t nbytes;
char buf[1024];
int i;
rv = apr_open(&f, fname, APR_READ | extra_flags, 0, p);
assert(!rv);
read_one(f, 'a');
read_one(f, 'b');
if (extra_flags & APR_BUFFERED) {
fprintf(stdout,
"\n\t\tskipping apr_ungetc() for APR_BUFFERED... "
"doesn't work yet...\n\t\t\t\t ");
}
else {
rv = apr_ungetc('b', f);
assert(!rv);
/* Note: some implementations move the file ptr back;
* others just save up to one char; it isn't
* portable to unget more than once.
*/
/* Don't do this: rv = apr_ungetc('a', f); */
read_one(f, 'b');
}
read_one(f, 'c');
read_one(f, '\n');
for (i = 0; i < TESTREAD_BLKSIZE; i++) {
read_one(f, 'a');
}
read_one(f, '\n');
read_one(f, '\n');
rv = apr_getc(buf, f);
assert(rv == APR_EOF);
rv = apr_close(f);
assert(!rv);
f = NULL;
rv = apr_open(&f, fname, APR_READ | extra_flags, 0, p);
assert(!rv);
rv = apr_fgets(buf, 10, f);
assert(!rv);
assert(!strcmp(buf, "abc\n"));
/* read first 800 of TESTREAD_BLKSIZE 'a's
*/
rv = apr_fgets(buf, 801, f);
assert(!rv);
assert(strlen(buf) == 800);
for (i = 0; i < 800; i++) {
assert(buf[i] == 'a');
}
/* read rest of the 'a's and the first newline
*/
rv = apr_fgets(buf, sizeof buf, f);
assert(!rv);
assert(strlen(buf) == TESTREAD_BLKSIZE - 800 + 1);
for (i = 0; i < TESTREAD_BLKSIZE - 800; i++) {
assert(buf[i] == 'a');
}
assert(buf[TESTREAD_BLKSIZE - 800] == '\n');
/* read the last newline
*/
rv = apr_fgets(buf, sizeof buf, f);
assert(!rv);
assert(!strcmp(buf, "\n"));
/* get APR_EOF
*/
rv = apr_fgets(buf, sizeof buf, f);
assert(rv == APR_EOF);
/* get APR_EOF with apr_getc
*/
rv = apr_getc(buf, f);
assert(rv == APR_EOF);
/* get APR_EOF with apr_read
*/
nbytes = sizeof buf;
rv = apr_read(f, buf, &nbytes);
assert(rv == APR_EOF);
rv = apr_close(f);
assert(!rv);
}
static void test_bigread(apr_pool_t *p, const char *fname, apr_int32_t extra_flags)
{
apr_file_t *f = NULL;
apr_status_t rv;
char buf[APR_BUFFERSIZE * 2];
apr_size_t nbytes;
/* Create a test file with known content.
*/
rv = apr_open(&f, fname, APR_CREATE | APR_WRITE | APR_TRUNCATE, APR_UREAD | APR_UWRITE, p);
if (rv) {
fprintf(stderr, "apr_open()->%d/%s\n",
rv, apr_strerror(rv, buf, sizeof buf));
exit(1);
}
nbytes = APR_BUFFERSIZE;
memset(buf, 0xFE, nbytes);
rv = apr_write(f, buf, &nbytes);
assert(!rv && nbytes == APR_BUFFERSIZE);
rv = apr_close(f);
assert(!rv);
f = NULL;
rv = apr_open(&f, fname, APR_READ | extra_flags, 0, p);
assert(!rv);
nbytes = sizeof buf;
rv = apr_read(f, buf, &nbytes);
assert(!rv);
assert(nbytes == APR_BUFFERSIZE);
rv = apr_close(f);
assert(!rv);
}
static void test_read(apr_pool_t *p)
{
const char *fname = "testread.dat";
apr_status_t rv;
fprintf(stdout, "Testing file read functions.\n");
create_testread(p, fname);
fprintf(stdout, "\tBuffered file tests......");
test_read_guts(p, fname, APR_BUFFERED);
fprintf(stdout, "OK\n");
fprintf(stdout, "\tUnbuffered file tests....");
test_read_guts(p, fname, 0);
fprintf(stdout, "OK\n");
fprintf(stdout, "\tMore buffered file tests......");
test_bigread(p, fname, APR_BUFFERED);
fprintf(stdout, "OK\n");
fprintf(stdout, "\tMore unbuffered file tests......");
test_bigread(p, fname, 0);
fprintf(stdout, "OK\n");
rv = apr_remove_file(fname, p);
assert(!rv);
fprintf(stdout, "\tAll read tests...........OK\n");
}