Index: include/apr_portable.h
===================================================================
--- include/apr_portable.h	(revision 603256)
+++ include/apr_portable.h	(working copy)
@@ -344,6 +344,22 @@
 /**
  * convert the file from os specific type to apr type.
  * @param file The apr file we are converting to.
+ * @param thefile The os specific file to convert
+ * @param flags The flags that were used to open this file.
+ * @param register_cleanup A cleanup will be registered on the apr_file_t
+ * @param cont The pool to use if it is needed.
+ * @remark On Unix, it is only possible to put a file descriptor into
+ *         an apr file type.
+ */
+APR_DECLARE(apr_status_t) apr_os_file_put_ex(apr_file_t **file,
+                                          apr_os_file_t *thefile,
+                                          apr_int32_t flags,
+                                          int register_cleanup,
+                                          apr_pool_t *cont); 
+
+/**
+ * convert the file from os specific type to apr type.
+ * @param file The apr file we are converting to.
  * @param thefile The os specific pipe to convert
  * @param cont The pool to use if it is needed.
  * @remark On Unix, it is only possible to put a file descriptor into
@@ -379,6 +395,21 @@
                                          apr_pool_t *cont); 
 
 /**
+ * convert the dir from os specific type to apr type.
+ * @param dir The apr dir we are converting to.
+ * @param dirname The full path to the directory (use / on all systems)
+ * @param thedir The os specific dir to convert
+ * @param register_cleanup A cleanup will be registered on the apr_dir_t
+ *   to issue apr_dir_close().
+ * @param cont The pool to use when creating to apr directory.
+ */
+APR_DECLARE(apr_status_t) apr_os_dir_put_ex(apr_dir_t **dir,
+                                         const char *dirname,
+                                         apr_os_dir_t *thedir,
+                                         int register_cleanup,
+                                         apr_pool_t *cont); 
+
+/**
  * Convert a socket from the os specific type to the apr type
  * @param sock The pool to use.
  * @param thesock The socket to convert to.
Index: include/apr_file_info.h
===================================================================
--- include/apr_file_info.h	(revision 603256)
+++ include/apr_file_info.h	(working copy)
@@ -246,6 +246,13 @@
                                        apr_pool_t *pool);
 
 /**
+ * return the dirname field of a directory
+ * @param name Pointer to new string containing directory name (on output)
+ * @param thedir the directory who's name should be returned.
+ */                        
+APR_DECLARE(apr_status_t) apr_dir_name_get(char **name, apr_dir_t *thedir);
+
+/**
  * close the specified directory. 
  * @param thedir the directory descriptor to close.
  */                        
Index: file_io/win32/dir.c
===================================================================
--- file_io/win32/dir.c	(revision 603256)
+++ file_io/win32/dir.c	(working copy)
@@ -103,6 +103,12 @@
     return rv;
 }
 
+APR_DECLARE(apr_status_t) apr_dir_name_get(char **name, apr_dir_t *dir)
+{
+    *name = dir->dirname;
+    return APR_SUCCESS;
+}
+
 APR_DECLARE(apr_status_t) apr_dir_close(apr_dir_t *dir)
 {
     apr_pool_cleanup_kill(dir->pool, dir, dir_cleanup);
@@ -391,3 +397,12 @@
 {
     return APR_ENOTIMPL;
 }
+
+APR_DECLARE(apr_status_t) apr_os_dir_put_ex(apr_dir_t **dir,
+                                         const char *dirname,
+                                         apr_os_dir_t *thedir,
+                                         int register_cleanup,
+                                         apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}
Index: file_io/win32/open.c
===================================================================
--- file_io/win32/open.c	(revision 603256)
+++ file_io/win32/open.c	(working copy)
@@ -431,35 +431,15 @@
         return apr_get_os_error();
     }
 
-    (*new) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t));
-    (*new)->pool = pool;
-    (*new)->filehand = handle;
-    (*new)->fname = apr_pstrdup(pool, fname);
-    (*new)->flags = flag;
-    (*new)->timeout = -1;
-    (*new)->ungetchar = -1;
-
     if (flag & APR_APPEND) {
-        (*new)->append = 1;
-        SetFilePointer((*new)->filehand, 0, NULL, FILE_END);
+        SetFilePointer(handle, 0, NULL, FILE_END);
     }
-    if (flag & APR_BUFFERED) {
-        (*new)->buffered = 1;
-        (*new)->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
-        (*new)->bufsize = APR_FILE_DEFAULT_BUFSIZE;
-    }
-    /* Need the mutex to handled buffered and O_APPEND style file i/o */
-    if ((*new)->buffered || (*new)->append) {
-        rv = apr_thread_mutex_create(&(*new)->mutex, 
-                                     APR_THREAD_MUTEX_DEFAULT, pool);
-        if (rv) {
-            if (file_cleanup(*new) == APR_SUCCESS) {
-                apr_pool_cleanup_kill(pool, *new, file_cleanup);
-            }
-            return rv;
-        }
-    }
 
+    if ((rv = apr_os_file_put_ex(new, &handle, flag, perm, !(flag & APR_FILE_NOCLEANUP), pool)) != APR_SUCCESS)
+        return rv;
+
+    (*new)->fname = apr_pstrdup(pool, fname);
+
 #if APR_HAS_UNICODE_FS
     if ((apr_os_level >= APR_WIN_2000) && ((*new)->flags & APR_FOPEN_SPARSE)) {
         if ((rv = make_sparse_file(*new)) != APR_SUCCESS)
@@ -474,14 +454,6 @@
         /* This feature is not supported on this platform. */
         (*new)->flags &= ~APR_FOPEN_SPARSE;
 
-    /* Create a pollset with room for one descriptor. */
-    /* ### check return codes */
-    (void) apr_pollset_create(&(*new)->pollset, 1, pool, 0);
-
-    if (!(flag & APR_FILE_NOCLEANUP)) {
-        apr_pool_cleanup_register((*new)->pool, (void *)(*new), file_cleanup,
-                                  apr_pool_cleanup_null);
-    }
     return APR_SUCCESS;
 }
 
@@ -590,12 +562,21 @@
                                           apr_int32_t flags,
                                           apr_pool_t *pool)
 {
+    return apr_os_file_put_ex(file, thefile, flags, 0, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_os_file_put_ex(apr_file_t **file,
+                                          apr_os_file_t *thefile,
+                                          apr_int32_t flags,
+                                          int register_cleanup,
+                                          apr_pool_t *pool)
+{
     (*file) = apr_pcalloc(pool, sizeof(apr_file_t));
     (*file)->pool = pool;
     (*file)->filehand = *thefile;
     (*file)->ungetchar = -1; /* no char avail */
     (*file)->timeout = -1;
-    (*file)->flags = flags;
+    (*file)->flags = flags|APR_FILE_NOCLEANUP;
 
     if (flags & APR_APPEND) {
         (*file)->append = 1;
@@ -622,6 +603,12 @@
     /* ### check return codes */
     (void) apr_pollset_create(&(*file)->pollset, 1, pool, 0);
 
+    if (register_cleanup) {
+        (*file)->flags &= ~APR_FILE_NOCLEANUP;
+        apr_pool_cleanup_register((*file)->pool, (void *)(*file), file_cleanup,
+                                  apr_pool_cleanup_null);
+    }
+
     /* Should we be testing if thefile is a handle to 
      * a PIPE and set up the mechanics appropriately?
      *
Index: file_io/os2/open.c
===================================================================
--- file_io/os2/open.c	(revision 603256)
+++ file_io/os2/open.c	(working copy)
@@ -36,15 +36,8 @@
     int mflags = OPEN_FLAGS_FAIL_ON_ERROR|OPEN_SHARE_DENYNONE|OPEN_FLAGS_NOINHERIT;
     int rv;
     ULONG action;
-    apr_file_t *dafile = (apr_file_t *)apr_palloc(pool, sizeof(apr_file_t));
+    apr_os_file_t fd;
 
-    dafile->pool = pool;
-    dafile->isopen = FALSE;
-    dafile->eof_hit = FALSE;
-    dafile->buffer = NULL;
-    dafile->flags = flag;
-    dafile->blocking = BLK_ON;
-    
     if ((flag & APR_READ) && (flag & APR_WRITE)) {
         mflags |= OPEN_ACCESS_READWRITE;
     } else if (flag & APR_READ) {
@@ -52,21 +45,9 @@
     } else if (flag & APR_WRITE) {
         mflags |= OPEN_ACCESS_WRITEONLY;
     } else {
-        dafile->filedes = -1;
         return APR_EACCES;
     }
 
-    dafile->buffered = (flag & APR_BUFFERED) > 0;
-
-    if (dafile->buffered) {
-        dafile->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
-        dafile->bufsize = APR_FILE_DEFAULT_BUFSIZE;
-        rv = apr_thread_mutex_create(&dafile->mutex, 0, pool);
-
-        if (rv)
-            return rv;
-    }
-
     if (flag & APR_CREATE) {
         oflags |= OPEN_ACTION_CREATE_IF_NEW;
 
@@ -83,33 +64,26 @@
     } else if ((oflags & 0xFF) == 0) {
         oflags |= OPEN_ACTION_OPEN_IF_EXISTS;
     }
+
+    rv = DosOpen(fname, &fd, &action, 0, 0, oflags, mflags, NULL);
     
-    rv = DosOpen(fname, &(dafile->filedes), &action, 0, 0, oflags, mflags, NULL);
-    
     if (rv == 0 && (flag & APR_APPEND)) {
         ULONG newptr;
-        rv = DosSetFilePtr(dafile->filedes, 0, FILE_END, &newptr );
+        rv = DosSetFilePtr(fd, 0, FILE_END, &newptr );
         
         if (rv)
-            DosClose(dafile->filedes);
+            DosClose(fd);
     }
     
     if (rv != 0)
         return APR_FROM_OS_ERROR(rv);
-    
-    dafile->isopen = TRUE;
-    dafile->fname = apr_pstrdup(pool, fname);
-    dafile->filePtr = 0;
-    dafile->bufpos = 0;
-    dafile->dataRead = 0;
-    dafile->direction = 0;
-    dafile->pipe = FALSE;
 
-    if (!(flag & APR_FILE_NOCLEANUP)) { 
-        apr_pool_cleanup_register(dafile->pool, dafile, apr_file_cleanup, apr_file_cleanup);
-    }
+    if ((rv = apr_os_file_put_ex(new, &fd, flag, !(flag & APR_FILE_NOCLEANUP), pool)) != APR_SUCCESS)
+        return rv;
 
-    *new = dafile;
+    (*new)->fname = apr_pstrdup(pool, fname);
+    (*new)->blocking = BLK_ON;
+
     return APR_SUCCESS;
 }
 
@@ -180,9 +154,13 @@
 }
 
 
-
 APR_DECLARE(apr_status_t) apr_os_file_put(apr_file_t **file, apr_os_file_t *thefile, apr_int32_t flags, apr_pool_t *pool)
 {
+    return apr_os_file_put_ex(file, thefile, flags, 0, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_os_file_put_ex(apr_file_t **file, apr_os_file_t *thefile, apr_int32_t flags, int register_cleanup, apr_pool_t *pool)
+{
     apr_os_file_t *dafile = thefile;
 
     (*file) = apr_palloc(pool, sizeof(apr_file_t));
@@ -190,7 +168,7 @@
     (*file)->filedes = *dafile;
     (*file)->isopen = TRUE;
     (*file)->eof_hit = FALSE;
-    (*file)->flags = flags;
+    (*file)->flags = flags|APR_FILE_NOCLEANUP;
     (*file)->pipe = FALSE;
     (*file)->buffered = (flags & APR_BUFFERED) > 0;
 
@@ -205,6 +183,11 @@
             return rv;
     }
 
+    if (register_cleanup) {
+        (*file)->flags &= ~APR_FILE_NOCLEANUP;
+        apr_pool_cleanup_register((*file)->pool, *file, apr_file_cleanup, apr_file_cleanup);
+    }
+
     return APR_SUCCESS;
 }    
 
Index: file_io/os2/dir.c
===================================================================
--- file_io/os2/dir.c	(revision 603256)
+++ file_io/os2/dir.c	(working copy)
@@ -31,21 +31,15 @@
 
 APR_DECLARE(apr_status_t) apr_dir_open(apr_dir_t **new, const char *dirname, apr_pool_t *pool)
 {
-    apr_dir_t *thedir = (apr_dir_t *)apr_palloc(pool, sizeof(apr_dir_t));
-    
-    if (thedir == NULL)
-        return APR_ENOMEM;
-    
-    thedir->pool = pool;
-    thedir->dirname = apr_pstrdup(pool, dirname);
+    *new = NULL;
+    return apr_os_dir_put_ex(new, dirname, &0, 1, pool);
+}
 
-    if (thedir->dirname == NULL)
-        return APR_ENOMEM;
 
-    thedir->handle = 0;
-    thedir->validentry = FALSE;
-    *new = thedir;
-    apr_pool_cleanup_register(pool, thedir, dir_cleanup, apr_pool_cleanup_null);
+
+APR_DECLARE(apr_status_t) apr_dir_name_get(char **name, apr_dir_t *dir)
+{
+    *name = dir->dirname;
     return APR_SUCCESS;
 }
 
@@ -158,10 +152,33 @@
 APR_DECLARE(apr_status_t) apr_os_dir_put(apr_dir_t **dir, apr_os_dir_t *thedir,
                                          apr_pool_t *pool)
 {
+    return apr_os_dir_put_ex(dir, NULL, thedir, 0, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_os_dir_put_ex(apr_dir_t **dir,
+                                         const char *dirname,
+                                         apr_os_dir_t *thedir,
+                                         int register_cleanup,
+                                         apr_pool_t *pool)
+{
     if ((*dir) == NULL) {
         (*dir) = (apr_dir_t *)apr_pcalloc(pool, sizeof(apr_dir_t));
         (*dir)->pool = pool;
+        (*dir)->validentry = FALSE;
+        if (register_cleanup) {
+            apr_pool_cleanup_register((*dir)->pool, *dir, dir_cleanup,
+                                    apr_pool_cleanup_null);
+        }
     }
+    else {
+        apr_pool_cleanup_run((*dir)->pool, *dir, dir_cleanup);
+    }
+
     (*dir)->handle = *thedir;
+
+    if (dirname) {
+        (*dir)->dirname = apr_pstrdup(pool, dirname);
+    }
+
     return APR_SUCCESS;
 }
Index: file_io/unix/open.c
===================================================================
--- file_io/unix/open.c	(revision 603256)
+++ file_io/unix/open.c	(working copy)
@@ -86,10 +86,7 @@
 {
     apr_os_file_t fd;
     int oflags = 0;
-#if APR_HAS_THREADS
-    apr_thread_mutex_t *thlock;
     apr_status_t rv;
-#endif
 
     if ((flag & APR_READ) && (flag & APR_WRITE)) {
         oflags = O_RDWR;
@@ -134,16 +131,6 @@
     }
 #endif
 
-#if APR_HAS_THREADS
-    if ((flag & APR_BUFFERED) && (flag & APR_XTHREAD)) {
-        rv = apr_thread_mutex_create(&thlock,
-                                     APR_THREAD_MUTEX_DEFAULT, pool);
-        if (rv) {
-            return rv;
-        }
-    }
-#endif
-
     if (perm == APR_OS_DEFAULT) {
         fd = open(fname, oflags, 0666);
     }
@@ -154,48 +141,13 @@
        return errno;
     }
 
-    (*new) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t));
-    (*new)->pool = pool;
-    (*new)->flags = flag;
-    (*new)->filedes = fd;
+    if ((rv = apr_os_file_put_ex(new, &fd, flag, !(flag & APR_FILE_NOCLEANUP), pool)) != APR_SUCCESS) {
+        return rv;
+    }
 
     (*new)->fname = apr_pstrdup(pool, fname);
-
     (*new)->blocking = BLK_ON;
-    (*new)->buffered = (flag & APR_BUFFERED) > 0;
 
-    if ((*new)->buffered) {
-        (*new)->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
-        (*new)->bufsize = APR_FILE_DEFAULT_BUFSIZE;
-#if APR_HAS_THREADS
-        if ((*new)->flags & APR_XTHREAD) {
-            (*new)->thlock = thlock;
-        }
-#endif
-    }
-    else {
-        (*new)->buffer = NULL;
-    }
-
-    (*new)->is_pipe = 0;
-    (*new)->timeout = -1;
-    (*new)->ungetchar = -1;
-    (*new)->eof_hit = 0;
-    (*new)->filePtr = 0;
-    (*new)->bufpos = 0;
-    (*new)->dataRead = 0;
-    (*new)->direction = 0;
-#ifndef WAITIO_USES_POLL
-    /* Start out with no pollset.  apr_wait_for_io_or_timeout() will
-     * initialize the pollset if needed.
-     */
-    (*new)->pollset = NULL;
-#endif
-    if (!(flag & APR_FILE_NOCLEANUP)) {
-        apr_pool_cleanup_register((*new)->pool, (void *)(*new), 
-                                  apr_unix_file_cleanup, 
-                                  apr_unix_child_file_cleanup);
-    }
     return APR_SUCCESS;
 }
 
@@ -235,6 +187,15 @@
                                           apr_os_file_t *thefile,
                                           apr_int32_t flags, apr_pool_t *pool)
 {
+    return apr_os_file_put_ex(file, thefile, flags, 0, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_os_file_put_ex(apr_file_t **file, 
+                                          apr_os_file_t *thefile,
+                                          apr_int32_t flags,
+                                          int register_cleanup,
+                                          apr_pool_t *pool)
+{
     int *dafile = thefile;
     
     (*file) = apr_pcalloc(pool, sizeof(apr_file_t));
@@ -268,6 +229,14 @@
         }
 #endif
     }
+
+    if (register_cleanup) {
+        (*file)->flags &= ~APR_FILE_NOCLEANUP;
+        apr_pool_cleanup_register((*file)->pool, (void *)(*file), 
+                                  apr_unix_file_cleanup, 
+                                  apr_unix_child_file_cleanup);
+    }
+
     return APR_SUCCESS;
 }    
 
Index: file_io/unix/dir.c
===================================================================
--- file_io/unix/dir.c	(revision 603256)
+++ file_io/unix/dir.c	(working copy)
@@ -71,29 +71,19 @@
 apr_status_t apr_dir_open(apr_dir_t **new, const char *dirname, 
                           apr_pool_t *pool)
 {
-    /* On some platforms (e.g., Linux+GNU libc), d_name[] in struct 
-     * dirent is declared with enough storage for the name.  On other
-     * platforms (e.g., Solaris 8 for Intel), d_name is declared as a
-     * one-byte array.  Note: gcc evaluates this at compile time.
-     */
-    apr_size_t dirent_size = 
-        sizeof(*(*new)->entry) +
-        (sizeof((*new)->entry->d_name) > 1 ? 0 : 255);
     DIR *dir = opendir(dirname);
 
     if (!dir) {
         return errno;
     }
 
-    (*new) = (apr_dir_t *)apr_palloc(pool, sizeof(apr_dir_t));
+    *new = NULL;
+    return apr_os_dir_put_ex(new, dirname, dir, 1, pool);
+}
 
-    (*new)->pool = pool;
-    (*new)->dirname = apr_pstrdup(pool, dirname);
-    (*new)->dirstruct = dir;
-    (*new)->entry = apr_pcalloc(pool, dirent_size);
-
-    apr_pool_cleanup_register((*new)->pool, *new, dir_cleanup,
-                              apr_pool_cleanup_null);
+apr_status_t apr_dir_name_get(char **name, apr_dir_t *dir)
+{
+    *name = dir->dirname;
     return APR_SUCCESS;
 }
 
@@ -348,12 +338,43 @@
 apr_status_t apr_os_dir_put(apr_dir_t **dir, apr_os_dir_t *thedir,
                           apr_pool_t *pool)
 {
+    return apr_os_dir_put_ex(dir, NULL, thedir, 0, pool);
+}
+
+apr_status_t apr_os_dir_put_ex(apr_dir_t **dir,
+                          const char *dirname,
+                          apr_os_dir_t *thedir,
+                          int register_cleanup,
+                          apr_pool_t *pool)
+{
+    /* On some platforms (e.g., Linux+GNU libc), d_name[] in struct 
+     * dirent is declared with enough storage for the name.  On other
+     * platforms (e.g., Solaris 8 for Intel), d_name is declared as a
+     * one-byte array.  Note: gcc evaluates this at compile time.
+     */
+    apr_size_t dirent_size = 
+        sizeof(*(*dir)->entry) +
+        (sizeof((*dir)->entry->d_name) > 1 ? 0 : 255);
+
     if ((*dir) == NULL) {
         (*dir) = (apr_dir_t *)apr_pcalloc(pool, sizeof(apr_dir_t));
         (*dir)->pool = pool;
+        (*dir)->entry = apr_pcalloc(pool, dirent_size);
+
+        if (register_cleanup) {
+            apr_pool_cleanup_register((*dir)->pool, *dir, dir_cleanup,
+                                      apr_pool_cleanup_null);
+        }
     }
+    else {
+        apr_pool_cleanup_run((*dir)->pool, *dir, dir_cleanup);
+    }
+
     (*dir)->dirstruct = thedir;
+
+    if (dirname) {
+        (*dir)->dirname = apr_pstrdup(pool, dirname);
+    }
+
     return APR_SUCCESS;
 }
-
-  
