<h2>File I/O</h2>

 ap_file_t *ap_open(ap_context_t *, char *, ap_int32_t, ap_fileperms_t mode)
	Open the specified file, and return a method for accessing that file.
     Arguments:
        arg 1)  The context to use.
	arg 2)  full path name to the file to be opened.
	arg 3)  Note: this may become its own type with accessor methods
                flags that determine how to open or create the file.  
	        Or'ed value of:
			APR_READ         Open for reading
			APR_WRITE        Open for writing
			APR_CREATE       Create the file if not there
			APR_APPEND	The file ptr is set to end prior to 
					write
			APR_TRUNCATE	If the file is there, length is 
					truncated to 0.
			APR_BINARY      Not a text file.
			APR_BUFFERED    buffer the data.  Default is 
					non-buffered
			APR_EXCL        return error if APR_CREATE and file
					exists.
	arg 4)  Access permissions to set for the file if it is created with
		APR_CREATE. We haven't decided how exactly we want this to
                work, but it will support the set of Unix permissions at
                minimum.
        return) The abstracted file descriptor for the file that was opened.  
	        NULL on error

Notes:  The values assigned when the file is opened is not kept current.  It is
        not garaunteed to be accurate after the file is opened.  It is intended
        for use in situations where the latency between opening and use a file
        is small, and a stat isn't required after opening the file. 


ap_status_t ap_close(ap_context_t *, ap_file_t *);
	Close the specified file descriptor
     Arguments:
        arg 1)  The context to use.
	arg 2)  file descriptor of file to be closed.
        return) APR_SUCCESS or APR_FAILURE

Notes:  The fields within the APRFile structure will not be changed when a file
	is closed.  The ONLY updated field, will be the file descriptor.

 ap_size_t ap_read(ap_context_t *, ap_file_t *, void *, ap_size_t)
	Read n bytes from file and store in buffer.
     Arguments:
        arg 1)  The context to use.
	arg 2)  File descriptor to read from
	arg 3)  buffer to store data in
	arg 4)  number of bytes to read
	return) pointer to number of bytes read.

 ap_size_t ap_write(ap_context_t *, ap_file_t *, void *, ap_size_t)
	Write n bytes of data from buffer to file
     Arguments:
        arg 1)  The context to use.
	arg 2)  File descriptor to write data to
	arg 3)  buffer to read data from
	arg 4)  number of bytes to write
	return) pointer to number of bytes written. 

Notes:  ap_write tries to update the ap_file_t that is passed in, but it fails
        silently if it is unable to do so.

 ap_file_t ap_dupfile(ap_context_t *, ap_file_t *)
        Copy data from one ap_file_t to a new one.
     Arguments:
        arg 1)  The context to use.
        arg 2)  the file info to save.
        return) a new file structure.

Notes:  This does not duplicate the file descriptor, it just saves the data
        from ap_file_t to a new ap_file_t.  This is used so user programs
        do not need access to the internals of ap_file_t

 ap_status ap_getfileinfo(ap_context_t *, char *, ap_file_t *)  
	Get information about the file with the given path name.
     Arguments:
        arg 1)  The context to use.
	arg 2)  path to file to get information about
	arg 3)  Structure to store file's information in. 
        return) APR_SUCCESS or APR_FAILURE.

 ap_status ap_updatefileinfo(ap_context_t *, ap_file_t *)  
	Get information about the file with the given path name.
     Arguments:
        arg 1)  The context to use.
	arg 2)  Structure to store file's information in. 
        return) APR_SUCCESS or APR_FAILURE.

Notes:  ap_updatefileinfo overwrites the old info, so if it is needed, the old
        info should be saved off to the side, using ap_dupfile.

 ap_off_t ap_seek(ap_context_t *, ap_file_t, ap_off_t, ap_seek_where_t)
	Moves the read/write file offset pointer
     Arguments:
        arg 1)  The context to use.
	arg 2)  Pointer to File descriptor  
	arg 3)  offset into file to move pointer to
	arg 4)	How to move the pointer.  See APRSeekWhere def below.
		    APR_SET -- set the offset to offset
                    APR_CUR -- add the offset to the current position
                    APR_END -- add the offset to the current file size.
	return) Offset into file that the pointer was set to.

 ap_status_t ap_remove_file(ap_context_t *, char *)
        Removes the file pointed to by the character string
     Arguments:
        arg 1)  The context to use.
        arg 2)  The full path of the file to delete.
        return) APR_SUCCESS or APR_FAILURE.
Notes:  If the file is still open, it will not actually be removed until the
        all references of the file are closed.

 ap_dir_t *ap_opendir(ap_context_t *, const char *)  
	Opens the specified directory stream.		
     Arguments:
        arg 1)  The context to use.
	arg 2)  path of the directory to be opened.
	return) abstracted directory descriptor structure.

 ap_status_t ap_closedir(ap_context_t *, ap_dir_t *)  
	closes the specified directory stream.		
     Arguments:
        arg 1)  The context to use.
	arg 2)  abstracted directory descriptor structure to be closed.
        return) APR_SUCCESS or APR_FAILURE

 ap_status_t *ap_readdir(ap_context_t *, ap_dir_t *)
	Retrieve the next directory entry from the specified directory.
     Arguments:
        arg 1)  The context to use.
	arg 2)  Abstracted directory descriptor to read from.
	return) APR_SUCCESS or APR_FAILURE.
NOTE:  This is garaunteed to have the files "." and ".." as the first two 
       files. 

 ap_status_t *ap_rewinddir(ap_context_t *, ap_dir_t *)
        Rewind directory to beginning of stream
     Arguments:
        arg 1)  The context to use.
        arg 2)  Directory structure to rewind
        return) APR_SUCCESS.  (POSIX does not allow this function to fail!)

 ap_status_t ap_make_dir(ap_context_t *, const char *, ap_fileperms_t)
        Create a new directory on the disk
     Arguments:
        arg 1)  The context to use.
        arg 2)  The path of the new directory.
        arg 3)  The permissions to set for the new directory.
        return) APR_SUCCESS or APR_FAILURE

 ap_status_t ap_remove_dir(ap_context_t *, const char *)
        Remove a direcotry from the disk
     Arguments:
        arg 1)  The context to use.
        arg 2)  The path of the directory to remove.
        return) APR_SUCCESS or APR_FAILURE
 
 char *ap_get_dir_filename(ap_context_t *, apr_dir_t *)
        Get the name of the current file in a directory.
     Arguments:
        arg 1)  The context to use
        arg 2)  The directory we care about.
        return) the file name
 
 ap_ssize_t ap_dir_entry_size(ap_context_t *, apr_dir_t *)
        Get the size of the current file in a directory.
     Arguments:
        arg 1)  The context to use
        arg 2)  The directory we care about.
        return) the size of the file in bytes 

 ap_time_t ap_dir_entry_mtime(ap_context_t *, apr_dir_t *)
        Get the last modified time of the current file in a directory.
     Arguments:
        arg 1)  The context to use
        arg 2)  The directory we care about.
        return) the time the file was last modified 

 ap_filetype_e ap_dir_entry_ftype(ap_context_t *, apr_dir_t *)
        Get the file type of the current file in a directory.
     Arguments:
        arg 1)  The context to use
        arg 2)  The directory we care about.
        return) the type of the file 

 ap_ssize_t ap_writev(ap_context_t *, ap_file_t, ap_iovec_t *, ap_ssize_t)
	Same as ap_write, except it gets the data from the APRIOVec array.
     Arguments:
        arg 1)  The context to use.
	arg 2)  File descriptor to write data to
	arg 3)  Array from which to get the data to write to the file
	arg 4)  Number of elements in the APRIOVec array.  Must be smaller
		than ap_MAX_IOVEC_SIZE, if not function will fail with
		APR_BUFFER_OVERFLOW_ERROR
	return) number of bytes written.  APR_FAILURE on failure.
Notes: ap_writev will write a complete entry from APRIOVec array before
       moving on to the next one.

 char * ap_get_filename(ap_context_t *, ap_file_t *)
        Get the name of an opened file. 
     Arguments:
        arg 1)  The context to use.
	arg 2)  File to get the name of 
	return) filename.  NULL on failure 

 ap_status_t ap_create_pipe(ap_context_t *, ap_file_t *, ap_file_t *)
        create an unnamed pipe
     Arguments:
        arg 1)  The context to use.
        arg 2)  File for reading from the pipe.
        arg 3)  File for writing to the pipe.
        return) APR_SUCCESS or APR_FAILURE
NOTE:  Unnamed pipes are ALWAYS inherited by any child process created by the
       process which created the pipes.  If the platform is storing the file
       name internally in apr, for pipes, this should be set to "PIPE" all in 
       caps.  This allows the program to easily determine what is a pipe, and 
       what isn't.  All other fields are left to the individual platform to
       set appropriately.  

 char *ap_create_namedpipe(ap_context_t *, char *, ap_fileperms_t)
        create a uniquely named pipe in the temp directory.
      Arguments:
        arg 1)  The context to use.
        arg 2)  The directory to create the named pipe in.  Can BE NULL! 
        arg 3)  The permissions for the named pipe.
        return) The name of the newly created pipe. (fully defined path) NULL
                on failure.
NOTE:  If directory name is NULL, the platform decides where it is best to put
       the pipe.  To get it in the current dir, use "." here :) 

**************** IMPLEMENTATION DETAILS **************

struct ap_file_t {
    int filedes;
    char * fname;
    int buffered;
    mode_t protection;
    uid_t user;
    gid_t group;
    off_t size;
    time_t atime;    
    time_t mtime;
    time_t ctime;
}

