Show Contents Previous Page Next Page
Chapter 11 - C API Reference Guide, Part II File and Directory Management In this section... Introduction Show Contents Go to Top Previous Page Next PageApache provides routines for opening files, reading and writing to them, and closing them. Some of these routines are wrappers around the standard operating system calls in order to provide a compatibility layer for the Unix, Win32, and other ports. Other functions are an improvement over their operating system equivalents because they take advantage of Apache's memory management system.
Pathname Manipulation Show Contents Go to Top Previous Page Next Page These routines are handy for parsing strings that contain filenames and paths.
See the next section, "Working with Files and Directories,"
for functions that operate on files and directories themselves.
These functions are all declared in httpd.h:
void ap_chdir_file (const char *file)
Given a pathname in file, this peculiar little function identifies the directory part and
invokes chdir() to make it the current working directory. Here's an example of calling the
function on the request record's filename field in order to chdir() to the directory that
contains the requested file:
ap_chdir_file(r->filename); int ap_os_is_path_absolute (const char *filename)
This function provides a portable test as to whether a filename is absolute or not. On
Unix systems, an absolute filename begins with a / , whereas under Win32 systems, an
absolute filename may begin with a drive letter, a colon delimiter, and a / or \ .
if(!ap_os_is_path_absolute(filename)) {
... must resolve the relative filename somehow ...
char *ap_make_full_path (pool *p, const char *directory, const char
*filename)
ap_make_full_path() will concatenate directory and filename and return the result. The function is smart about checking the directory string for a terminating slash and automatically
inserting one if needed.
int ap_is_directory (const char *path)
This function returns true if path exists and is a directory, false otherwise.
int ap_count_dirs (const char *path)
Given a pathname path, ap_count_dirs() counts the number of directories contained in the
path. This function merely counts the number of occurrences of the slash character in
the path. It doesn't actually check that any of the directories exist.
void ap_no2slash (char *path)
It is easy to inadvertently introduce multiple slashes into pathnames when concatenating
directories and filenames. Although both the filesystem and URIs are resistant to
repeated slashes, you can use this function to make constructed paths more aesthetic by
folding multiple slashes into a single one. It changes the provided pathname in place
and does not return a function result. The following example will remove the double-slash from the path /home/httpd/docs//
oops.html .
char *oops = ap_pstrdup(r->pool, "home/httpd/docs//oops.html");
ap_no2slash(oops);
char *ap_make_dirstr_prefix (char *prefix, const char *path, int n)
This highly specialized function will copy, at most, n leading directories found in path
into the character array at prefix, ensuring that prefix will terminate in a slash. You must
ensure that prefix is large enough to hold the resulting data--potentially the length of
path plus one extra byte for the string terminator. The function returns a pointer to the
end of prefix, in anticipation of your appending more data (typically a filename) onto the
end of the string. The following example shows one way to make a copy of the path to the parent directory
of the currently requested file:
char* path = r->filename;
char* prefix = (char*)ap_palloc(r->pool, strlen(path)+1);
ap_make_dirstr_prefix(prefix, path, ap_count_dirs(path)-1);
In case this was less than crystal clear, here is an example input/output table:
path
|
n
|
prefix
|
/a/b/c
|
1
|
/
|
/a/b/c
|
2
|
/a/
|
/a/b/c
|
3
|
/a/b/
|
/a/b/c
|
4
|
/a/b/c
|
/a/b/c
|
5
|
/a/b/c
|
char *ap_make_dirstr_parent (pool *p, const char *filename)
This function returns a new string containing the parent directory in which filename lives.
This is a much easier way to accomplish the same thing as the example given in the previous
section, and probably a little faster as well. ap_make_dirstr_parent() operates entirely
on the string level. It doesn't actually check that any of the directories exist.
char *dirname = ap_make_dirstr_parent(r->pool, r->filename);
void ap_getparents (char *filename)
Passed a file path in filename, the ap_getparents() function strips out any relative path components
by removing references to the .. and . directories. The stripping method follows
the four parsing phases described in RFC 1808. The operation is performed in
place just like ap_no2slash(). You should perform this operation before opening files based on user-provided input.
Otherwise, it might be possible for a malicious user to trick your module into opening a
file in a directory outside the document root. (Microsoft Internet Information Server
has been bitten by this bug several times.) By the time your handler finds the requested URI in the request record, Apache has
already passed it through ap_getparents(), so there is no need to call the function a second
time. However, you will still need to run the function on any paths passed in fill-out
forms and possibly on paths entered in configuration variables as well.
Working with Files and Directories Show Contents Go to Top Previous Page Next Page
Apache provides a series of wrappers around the C library routines that open and close files and directories. The main purpose of these routines is to take advantage of the resource pool API. Any files and directories that you open using the API calls will be automatically closed and their data structures deallocated when the current resource pool is destroyed.
These routines all live in alloc.h:
FILE *ap_pfopen (pool *p, const char *name, const char *fmode)
ap_pfopen() is a wrapper around the standard fopen() call. In addition to ensuring that the
FILE* is closed when the pool is destroyed, it provides some internal compatibility code
that ensures that the append (a) mode works the same on all platforms. In this example, the file indicated in r->filename is opened for reading:
FILE *fh = ap_pfopen(r->pool, r->filename, "r"); int ap_pfclose (pool *p, FILE *fh)
Although files opened with ap_pfopen() will be closed automatically for you when the
transaction is finished, you may close them sooner using ap_pfclose(). Be sure to use this
call rather than the standard fclose() so that Apache will know to cancel the scheduled
cleanup.
ap_pfclose(r->pool, fh);
FILE *ap_pfdopen (pool *p, int fd, const char *fmode)
This function works like the standard fdopen() call to create a new FILE* attached to the
indicated file descriptor. Like ap_pfopen(), the file is automatically closed when the pool
is cleaned up.
FILE *fh = ap_pfdopen(r->pool, fd, "r");
int ap_popenf (pool *p, const char *name, int flags, int mode) int ap_pclosef (struct pool *p, int fd)
These calls are equivalent to the standard open() and close() calls. ap_popenf() opens the
indicated file and returns a file descriptor, or -1 if the file could not be opened. ap_
pclosef() closes the file and cancels the scheduled cleanup before pool destruction.
int fd = ap_popenf(r->pool, r->filename, O_RDONLY, 0600);
read(fd, buffer, 1024);
ap_pclosef(fd);
void ap_note_cleanups_for_file (pool *p, FILE *fp)
If a module has opened a FILE* stream with a function other than ap_pfopen(), it can use
this function to ensure the file will be closed when the given pool is destroyed.
FILE *fp = tmpfile();
ap_note_cleanups_for_file(r->pool, fp);
void ap_note_cleanups_for_fd (pool *p, int fd)
If a module has opened a file descriptor with a function other than ap_pfdopen(), it can
use this function to ensure the descriptor will be closed when the given pool is
destroyed.
int fd = open(tempfile, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0622);
if (fd == -1) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
"error creating temporary file %s", tempfile);
return HTTP_INTERNAL_SERVER_ERROR;
}
ap_note_cleanups_for_fd(r->pool, fd);
void ap_kill_cleanups_for_fd (pool *p, int fd)
If a file descriptor has been registered to be closed with ap_note_cleanups_for_fd(), this
function can be used to unregister the cleanup.
ap_kill_cleanups_for_fd(r->pool, fd); DIR *ap_popendir (pool *p, const char *name) void ap_pclosedir (pool *p, DIR *d)
These functions correspond to the opendir() and closedir() calls. Like the other functions
in this section, directory handles allocated with ap_popendir() are automatically closed and
cleaned up for you when the pool is destroyed. You can close the directory earlier with
ap_pclosedir(). In this example, we check to see whether the requested filename is a directory. If so, we
open it as a directory rather than as a file.
if(S_ISDIR(r->finfo.st_mode)) {
DIR *dh = ap_popendir(r->pool, r->filename);
...
ap_pclosedir(r->pool, dh);
}
int ap_psocket (pool *p, int domain, int type, int protocol) int ap_pclosesocket (pool *p, int sock)
ap_psocket() is a wrapper around the socket() system
call. The socket is closed when the pool is destroyed. The ap_pclosesocket()
function closes a socket previously opened with ap_psocket(), canceling
the scheduled cleanup.
int sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP);
...
ap_pclosesocket(p, sock);
Show Contents Go to Top Previous Page Next Page Copyright © 1999 by O'Reilly & Associates, Inc. |