Doh

----- Original Message ----- 
From: "William A. Rowe, Jr." <[EMAIL PROTECTED]>
To: <[email protected]>
Sent: Monday, January 22, 2001 8:27 PM
Subject: [Patch] apr_dir_read


> Guys...
> 
>   a biggish patch, and the three specific apr_dir_read implementations are
> not complete or optimal.  I am taking a bit of a break, so I thought I would
> toss this out while folks are still awake.
> 
>   To avoid big stat() requirements unless that's exactly what we aim to
> accomplish, I've added APR_FINFO_DIRENT as an alias for the 'stock' info
> (certainly d_name, perhaps d_fileno?)
> 
>   Anyways, have a look, I have more testing on the win32 side, and a few
> changes rbb suggested on the unix side.
> 
> Bill
> 
Index: srclib/apr/include/apr_file_info.h
===================================================================
RCS file: /home/cvs/apr/include/apr_file_info.h,v
retrieving revision 1.4
diff -u -r1.4 apr_file_info.h
--- srclib/apr/include/apr_file_info.h  2001/01/20 22:18:55     1.4
+++ srclib/apr/include/apr_file_info.h  2001/01/23 02:17:04
@@ -145,6 +145,7 @@
 #define APR_FINFO_CSIZE  0x00000400
 #define APR_FINFO_DEV    0x00001000
 #define APR_FINFO_INODE  0x00002000
+#define APR_FINFO_NLINK  0x00004000
 #define APR_FINFO_TYPE   0x00008000
 #define APR_FINFO_USER   0x00010000 
 #define APR_FINFO_GROUP  0x00020000 
@@ -152,13 +153,14 @@
 #define APR_FINFO_GPROT  0x00200000
 #define APR_FINFO_WPROT  0x00400000
 #define APR_FINFO_ICASE  0x01000000  /*  if dev is case insensitive */
-#define APR_FINFO_FCASE  0x02000000  /*  filename in proper case */
+#define APR_FINFO_NAME   0x02000000  /*  ->name in proper case */
 
 #define APR_FINFO_MIN    0x00008170  /*  minimal: type, dates and size */
 #define APR_FINFO_IDENT  0x00003000  /*  dev and inode */
 #define APR_FINFO_OWNER  0x00030000  /*  user and group */
 #define APR_FINFO_PROT   0x00700000  /*  all protections */
-#define APR_FINFO_NORM   0x0073b170  /*  the expected unix results */
+#define APR_FINFO_NORM   0x0073f170  /*  an atomic unix apr_stat() */
+#define APR_FINFO_DIRENT 0x01002000  /*  an atomic unix apr_dir_read() */
 
 /**
  * The file information structure.  This is analogous to the POSIX
@@ -184,6 +186,8 @@
     apr_ino_t inode;
     /** The id of the device the file is on. */
     apr_dev_t device;
+    /** The number of hard links to the file. */
+    apr_int16_t nlink;
     /** The size of the file */
     apr_off_t size;
     /** The space allocated for the file */
@@ -198,8 +202,8 @@
     apr_time_t ctime;
     /** The full pathname of the file */
     const char *fname;
-    /** The file's name alone, in filesystem case */
-    char *fcase;
+    /** The file's name (no path) in filesystem case */
+    const char *name;
     /** The file's handle, if accessed (can be submitted to apr_duphandle) */
     struct apr_file_t *filehand;
 };
@@ -247,60 +251,26 @@
 /**
  * close the specified directory. 
  * @param thedir the directory descriptor to close.
- * @deffunc apr_status_t apr_closedir(apr_dir_t *thedir)
+ * @deffunc apr_status_t apr_dir_close(apr_dir_t *thedir)
  */                        
-APR_DECLARE(apr_status_t) apr_closedir(apr_dir_t *thedir);
+APR_DECLARE(apr_status_t) apr_dir_close(apr_dir_t *thedir);
 
 /**
  * Read the next entry from the specified directory. 
  * @param thedir the directory descriptor to read from, and fill out.
  * @tip All systems return . and .. as the first two files.
- * @deffunc apr_status_t apr_readdir(apr_dir_t *thedir)
+ * @deffunc apr_status_t apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted, 
apr_dir_t *thedir)
  */                        
-APR_DECLARE(apr_status_t) apr_readdir(apr_dir_t *thedir);
+APR_DECLARE(apr_status_t) apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted,
+                                       apr_dir_t *thedir);
 
 /**
  * Rewind the directory to the first entry.
  * @param thedir the directory descriptor to rewind.
- * @deffunc apr_status_t apr_rewinddir(apr_dir_t *thedir)
+ * @deffunc apr_status_t apr_dir_rewind(apr_dir_t *thedir)
  */                        
-APR_DECLARE(apr_status_t) apr_rewinddir(apr_dir_t *thedir);
+APR_DECLARE(apr_status_t) apr_dir_rewind(apr_dir_t *thedir);
 
-/**
- * Get the file name of the current directory entry.
- * @param new_path the file name of the directory entry. 
- * @param thedir the currently open directory.
- * @deffunc apr_status_t apr_get_dir_filename(const char **new_path, apr_dir_t 
*thedir)
- */                        
-APR_DECLARE(apr_status_t) apr_get_dir_filename(const char **new_path, 
-                                               apr_dir_t *thedir);
-
-/**
- * Get the size of the current directory entry.
- * @param size the size of the directory entry. 
- * @param thedir the currently open directory.
- * @deffunc apr_status_t apr_dir_entry_size(apr_size_t *size, apr_dir_t 
*thedir)
- */                        
-APR_DECLARE(apr_status_t) apr_dir_entry_size(apr_size_t *size, 
-                                             apr_dir_t *thedir);
-
-/**
- * Get the last modified time of the current directory entry.
- * @param mtime the last modified time of the directory entry. 
- * @param thedir the currently open directory.
- * @deffunc apr_status_t apr_dir_entry_mtime(apr_time_t *mtime, apr_dir_t 
*thedir)
- */ 
-APR_DECLARE(apr_status_t) apr_dir_entry_mtime(apr_time_t *mtime, 
-                                              apr_dir_t *thedir);
-
-/**
- * Get the file type of the current directory entry.
- * @param type the file type of the directory entry. 
- * @param thedir the currently open directory.
- * @deffunc apr_status_t apr_dir_entry_ftype(apr_filetype_e *type, apr_dir_t 
*thedir)
- */
-APR_DECLARE(apr_status_t) apr_dir_entry_ftype(apr_filetype_e *type, 
-                                              apr_dir_t *thedir);
 
 #ifdef __cplusplus
 }
Index: modules/dav/fs/repos.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/dav/fs/repos.c,v
retrieving revision 1.44
diff -u -r1.44 repos.c
--- modules/dav/fs/repos.c      2001/01/20 21:42:17     1.44
+++ modules/dav/fs/repos.c      2001/01/23 02:16:56
@@ -1315,6 +1315,7 @@
     apr_pool_t *pool = params->pool;
     dav_error *err = NULL;
     int isdir = fsctx->res1.collection;
+    apr_finfo_t dirent;
     apr_dir_t *dirp;
 
     /* ensure the context is prepared properly, then call the func */
@@ -1357,15 +1358,14 @@
        /* ### need a better error */
        return dav_new_error(pool, HTTP_NOT_FOUND, 0, NULL);
     }
-    while ((apr_readdir(dirp)) == APR_SUCCESS) {
-       const char *name;
+    while ((apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp)) == APR_SUCCESS) {
        apr_size_t len;
 
-       apr_get_dir_filename(&name, dirp);
-       len = strlen(name);
+       len = strlen(dirent.name);
 
        /* avoid recursing into our current, parent, or state directories */
-       if (name[0] == '.' && (len == 1 || (name[1] == '.' && len == 2))) {
+       if (dirent.name[0] == '.' 
+              && (len == 1 || (dirent.name[1] == '.' && len == 2))) {
            continue;
        }
 
@@ -1374,19 +1374,21 @@
            /* ### example: .htaccess is normally configured to fail auth */
 
            /* stuff in the state directory is never authorized! */
-           if (!strcmp(name, DAV_FS_STATE_DIR)) {
+           if (!strcmp(dirent.name, DAV_FS_STATE_DIR)) {
                continue;
            }
        }
        /* skip the state dir unless a HIDDEN is performed */
        if (!(params->walk_type & DAV_WALKTYPE_HIDDEN)
-           && !strcmp(name, DAV_FS_STATE_DIR)) {
+           && !strcmp(dirent.name, DAV_FS_STATE_DIR)) {
            continue;
        }
 
        /* append this file onto the path buffer (copy null term) */
-       dav_buffer_place_mem(pool, &fsctx->path1, name, len + 1, 0);
+       dav_buffer_place_mem(pool, &fsctx->path1, dirent.name, len + 1, 0);
 
+
+        /* ### Optimize me, dirent can give us what we need! */
         if (apr_lstat(&fsctx->info1.finfo, fsctx->path1.buf, 
                       APR_FINFO_NORM, pool) != APR_SUCCESS) {
            /* woah! where'd it go? */
@@ -1397,11 +1399,11 @@
 
        /* copy the file to the URI, too. NOTE: we will pad an extra byte
           for the trailing slash later. */
-       dav_buffer_place_mem(pool, &fsctx->uri_buf, name, len + 1, 1);
+       dav_buffer_place_mem(pool, &fsctx->uri_buf, dirent.name, len + 1, 1);
 
        /* if there is a secondary path, then do that, too */
        if (fsctx->path2.buf != NULL) {
-           dav_buffer_place_mem(pool, &fsctx->path2, name, len + 1, 0);
+           dav_buffer_place_mem(pool, &fsctx->path2, dirent.name, len + 1, 0);
        }
 
        /* set up the (internal) pathnames for the two resources */
@@ -1458,7 +1460,7 @@
     }
 
     /* ### check the return value of this? */
-    apr_closedir(dirp);
+    apr_dir_close(dirp);
 
     if (err != NULL)
        return err;
Index: modules/generators/mod_autoindex.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/generators/mod_autoindex.c,v
retrieving revision 1.53
diff -u -r1.53 mod_autoindex.c
--- modules/generators/mod_autoindex.c  2001/01/19 07:04:20     1.53
+++ modules/generators/mod_autoindex.c  2001/01/23 02:16:57
@@ -1540,8 +1540,8 @@
     char *title_name = ap_escape_html(r->pool, r->uri);
     char *title_endp;
     char *name = r->filename;
-
-    apr_dir_t *d;
+    apr_finfo_t dirent;
+    apr_dir_t *thedir;
     apr_status_t status;
     int num_ent = 0, x;
     struct ent *head, *p;
@@ -1551,7 +1551,7 @@
     char keyid;
     char direction;
 
-    if ((status = apr_dir_open(&d, name, r->pool)) != APR_SUCCESS) {
+    if ((status = apr_dir_open(&thedir, name, r->pool)) != APR_SUCCESS) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
                    "Can't open directory for index: %s", r->filename);
        return HTTP_FORBIDDEN;
@@ -1569,7 +1569,7 @@
     ap_send_http_header(r);
 
     if (r->header_only) {
-       apr_closedir(d);
+       apr_dir_close(thedir);
        return 0;
     }
 
@@ -1621,10 +1621,8 @@
      * linked list and then arrayificate them so qsort can use them. 
      */
     head = NULL;
-    while (apr_readdir(d) == APR_SUCCESS) {
-        const char *d_name;
-        apr_get_dir_filename(&d_name, d);
-       p = make_autoindex_entry(d_name, autoindex_opts,
+    while (apr_dir_read(&dirent, APR_FINFO_DIRENT, thedir) == APR_SUCCESS) {
+       p = make_autoindex_entry(dirent.name, autoindex_opts,
                                 autoindex_conf, r, keyid, direction);
        if (p != NULL) {
            p->next = head;
@@ -1647,7 +1645,7 @@
     }
     output_directories(ar, num_ent, autoindex_conf, r, autoindex_opts, keyid,
                       direction);
-    apr_closedir(d);
+    apr_dir_close(thedir);
 
     if (autoindex_opts & FANCY_INDEXING) {
        ap_rputs("<HR>\n", r);
Index: modules/mappers/mod_negotiation.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/mappers/mod_negotiation.c,v
retrieving revision 1.49
diff -u -r1.49 mod_negotiation.c
--- modules/mappers/mod_negotiation.c   2001/01/20 21:42:19     1.49
+++ modules/mappers/mod_negotiation.c   2001/01/23 02:16:58
@@ -912,6 +912,7 @@
     char *filp;
     int prefix_len;
     apr_dir_t *dirp;
+    apr_finfo_t dirent;
     apr_status_t status;
     struct var_rec mime_info;
     struct accept_rec accept_info;
@@ -936,17 +937,14 @@
         return HTTP_FORBIDDEN;
     }
 
-    while (apr_readdir(dirp) == APR_SUCCESS) {
+    while (apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp) == APR_SUCCESS) {
         request_rec *sub_req;
-        const char *d_name;
-
-        apr_get_dir_filename(&d_name, dirp);
+        
         /* Do we have a match? */
-
-        if (strncmp(d_name, filp, prefix_len)) {
+        if (strncmp(dirent.name, filp, prefix_len)) {
             continue;
         }
-        if (d_name[prefix_len] != '.') {
+        if (dirent.name[prefix_len] != '.') {
             continue;
         }
 
@@ -955,7 +953,7 @@
          * which we'll be slapping default_type on later).
          */
 
-        sub_req = ap_sub_req_lookup_file(d_name, r, NULL);
+        sub_req = ap_sub_req_lookup_file(dirent.name, r, NULL);
 
         /* If it has a handler, we'll pretend it's a CGI script,
          * since that's a good indication of the sort of thing it
@@ -979,7 +977,7 @@
             ((sub_req->handler) &&
              !strcmp(sub_req->handler, "type-map"))) {
 
-            apr_closedir(dirp);
+            apr_dir_close(dirp);
             neg->avail_vars->nelts = 0;
             if (sub_req->status != HTTP_OK) {
                 return sub_req->status;
@@ -990,7 +988,7 @@
         /* Have reasonable variant --- gather notes. */
 
         mime_info.sub_req = sub_req;
-        mime_info.file_name = apr_pstrdup(neg->pool, d_name);
+        mime_info.file_name = apr_pstrdup(neg->pool, dirent.name);
         if (sub_req->content_encoding) {
             mime_info.content_encoding = sub_req->content_encoding;
         }
@@ -1009,7 +1007,7 @@
         clean_var_rec(&mime_info);
     }
 
-    apr_closedir(dirp);
+    apr_dir_close(dirp);
 
     set_vlist_validator(r, r);
 
Index: modules/mappers/mod_speling.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/mappers/mod_speling.c,v
retrieving revision 1.26
diff -u -r1.26 mod_speling.c
--- modules/mappers/mod_speling.c       2001/01/19 07:04:23     1.26
+++ modules/mappers/mod_speling.c       2001/01/23 02:16:58
@@ -237,7 +237,7 @@
 {
     spconfig *cfg;
     char *good, *bad, *postgood, *url;
-    const char *fname;
+    apr_finfo_t dirent;
     int filoc, dotloc, urlen, pglen;
     apr_array_header_t *candidates = NULL;
     apr_dir_t          *dir;
@@ -310,8 +310,7 @@
         dotloc = strlen(bad);
     }
 
-    while (apr_readdir(dir) == APR_SUCCESS &&
-          apr_get_dir_filename(&fname, dir) == APR_SUCCESS) {
+    while (apr_dir_read(&dirent, APR_FINFO_DIRENT, dir) == APR_SUCCESS) {
         sp_reason q;
 
         /*
@@ -319,8 +318,8 @@
          * requested one, we must have found a broken symlink or some such.
          * Do _not_ try to redirect this, it causes a loop!
          */
-        if (strcmp(bad, fname) == 0) {
-            apr_closedir(dir);
+        if (strcmp(bad, dirent.name) == 0) {
+            apr_dir_close(dir);
             return OK;
         }
 
@@ -328,11 +327,11 @@
          * miscapitalization errors are checked first (like, e.g., lower case
          * file, upper case request)
          */
-        else if (strcasecmp(bad, fname) == 0) {
+        else if (strcasecmp(bad, dirent.name) == 0) {
             misspelled_file *sp_new;
 
            sp_new = (misspelled_file *) apr_push_array(candidates);
-            sp_new->name = apr_pstrdup(r->pool, fname);
+            sp_new->name = apr_pstrdup(r->pool, dirent.name);
             sp_new->quality = SP_MISCAPITALIZED;
         }
 
@@ -340,11 +339,11 @@
          * simple typing errors are checked next (like, e.g.,
          * missing/extra/transposed char)
          */
-        else if ((q = spdist(bad, fname)) != SP_VERYDIFFERENT) {
+        else if ((q = spdist(bad, dirent.name)) != SP_VERYDIFFERENT) {
             misspelled_file *sp_new;
 
            sp_new = (misspelled_file *) apr_push_array(candidates);
-            sp_new->name = apr_pstrdup(r->pool, fname);
+            sp_new->name = apr_pstrdup(r->pool, dirent.name);
             sp_new->quality = q;
         }
 
@@ -380,23 +379,23 @@
              * (e.g. foo.gif and foo.html) This code will pick the first one
              * it finds. Better than a Not Found, though.
              */
-            int entloc = ap_ind(fname, '.');
+            int entloc = ap_ind(dirent.name, '.');
             if (entloc == -1) {
-                entloc = strlen(fname);
+                entloc = strlen(dirent.name);
            }
 
             if ((dotloc == entloc)
-                && !strncasecmp(bad, fname, dotloc)) {
+                && !strncasecmp(bad, dirent.name, dotloc)) {
                 misspelled_file *sp_new;
 
                sp_new = (misspelled_file *) apr_push_array(candidates);
-                sp_new->name = apr_pstrdup(r->pool, fname);
+                sp_new->name = apr_pstrdup(r->pool, dirent.name);
                 sp_new->quality = SP_VERYDIFFERENT;
             }
 #endif
         }
     }
-    apr_closedir(dir);
+    apr_dir_close(dir);
 
     if (candidates->nelts != 0) {
         /* Wow... we found us a mispelling. Construct a fixed url */
Index: server/config.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/config.c,v
retrieving revision 1.104
diff -u -r1.104 config.c
--- server/config.c     2001/01/21 22:14:16     1.104
+++ server/config.c     2001/01/23 02:17:00
@@ -1280,6 +1280,7 @@
      */
     if (ap_is_rdirectory(ptemp, fname)) {
         apr_dir_t *dirp;
+        apr_finfo_t dirent;
        int current;
        apr_array_header_t *candidates = NULL;
        fnames *fnew;
@@ -1300,17 +1301,15 @@
            exit(1);
        }
        candidates = apr_make_array(p, 1, sizeof(fnames));
-        while (apr_readdir(dirp) == APR_SUCCESS) {
-            const char *d_name;
-           apr_get_dir_filename(&d_name, dirp);
-           /* strip out '.' and '..' */
-           if (strcmp(d_name, ".") &&
-               strcmp(d_name, "..")) {
+        while (apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp) == APR_SUCCESS) {
+            /* strip out '.' and '..' */
+           if (strcmp(dirent.name, ".") &&
+               strcmp(dirent.name, "..")) {
                fnew = (fnames *) apr_push_array(candidates);
-               fnew->fname = ap_make_full_path(p, fname, d_name);
+               fnew->fname = ap_make_full_path(p, fname, dirent.name);
            }
        }
-       apr_closedir(dirp);
+       apr_dir_close(dirp);
        if (candidates->nelts != 0) {
             qsort((void *) candidates->elts, candidates->nelts,
               sizeof(fnames), fname_alphasort);
Index: srclib/apr/file_io/os2/dir.c
===================================================================
RCS file: /home/cvs/apr/file_io/os2/dir.c,v
retrieving revision 1.21
diff -u -r1.21 dir.c
--- srclib/apr/file_io/os2/dir.c        2001/01/05 19:40:05     1.21
+++ srclib/apr/file_io/os2/dir.c        2001/01/23 02:17:04
@@ -64,7 +64,7 @@
 static apr_status_t dir_cleanup(void *thedir)
 {
     apr_dir_t *dir = thedir;
-    return apr_closedir(dir);
+    return apr_dir_close(dir);
 }
 
 
@@ -91,7 +91,7 @@
 
 
 
-apr_status_t apr_closedir(apr_dir_t *thedir)
+apr_status_t apr_dir_close(apr_dir_t *thedir)
 {
     int rv = 0;
     
@@ -108,7 +108,8 @@
 
 
 
-apr_status_t apr_readdir(apr_dir_t *thedir)
+apr_status_t apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted,
+                          apr_dir_t *thedir)
 {
     int rv;
     ULONG entries = 1;
@@ -122,24 +123,62 @@
         rv = DosFindNext(thedir->handle, &thedir->entry, 
sizeof(thedir->entry), &entries);
     }
 
-    if (rv == 0 && entries == 1) {
+    if (rv == 0 && entries == 1) 
+    {
+        /* XXX: Optimize the heck out of this case - whatever we know, report,
+         *      and then stat only if we must (e.g. wanted & APR_FINFO_TYPE)
+         */
         thedir->validentry = TRUE;
+
+        wanted &= ~(APR_FINFO_NAME | APR_FINFO_MTIME | APR_FINFO_SIZE);
+
+        if (wanted == APR_FINFO_TYPE && thedir->entry.attrFile & 
FILE_DIRECTORY)
+            wanted = 0;
+        
+        if (wanted)
+        {
+            char fspec[_MAXPATH];
+            int off;
+            apr_strcpyn(fspec, sizeof(fspec), thedir->dirname);
+            off = strlen(fspec);
+            if (fspec[off - 1] != '/')
+                fspec[off++] = '/';
+            apr_strcpyn(fspec + off, sizeof(fspec) - off, 
thedir->entry->d_name);
+            /* ??? Or lstat below?, I know, OS2 doesn't do symlinks */
+            ret = apr_stat(finfo, wanted, fspec, thedir->cntxt);
+        }
+        if (!wanted || ret) {
+            finfo->cntxt = thedir->cntxt;
+            finfo->valid = 0;
+        }
+        
+        finfo->valid |= APR_FINFO_NAME | APR_FINFO_MTIME | APR_FINFO_SIZE;
+        finfo->size = thedir->entry.cbFile;
+        apr_os2_time_to_apr_time(finfo->mtime, thedir->entry.fdateLastWrite, 
+                                 thedir->entry.ftimeLastWrite);
+        finfo->name = thedir->entry.achName;
+        if (thedir->entry.attrFile & FILE_DIRECTORY) {
+            finfo->filetype = APR_DIR;
+            finfo->valid |= APR_FINFO_TYPE;
+            return APR_SUCCESS;
+        }
+        
         return APR_SUCCESS;
     }
-        
+
     thedir->validentry = FALSE;
-    
+
     if (rv)
         return APR_OS2_STATUS(rv);
-    
+
     return APR_ENOENT;
 }
 
 
 
-apr_status_t apr_rewinddir(apr_dir_t *thedir)
+apr_status_t apr_dir_rewind(apr_dir_t *thedir)
 {
-    return apr_closedir(thedir);
+    return apr_dir_close(thedir);
 }
 
 
@@ -158,72 +197,5 @@
 
 
 
-apr_status_t apr_dir_entry_size(apr_size_t *size, apr_dir_t *thedir)
-{
-    if (thedir->validentry) {
-        *size = thedir->entry.cbFile;
-        return APR_SUCCESS;
-    }
-    
-    return APR_ENOFILE;
-}
-
 
 
-apr_status_t apr_dir_entry_mtime(apr_time_t *time, apr_dir_t *thedir)
-{
-    if (thedir->validentry) {
-        apr_os2_time_to_apr_time(time, thedir->entry.fdateLastWrite, 
-                                 thedir->entry.ftimeLastWrite);
-        return APR_SUCCESS;
-    }
-
-    return APR_ENOFILE;
-}
-
-
-
-apr_status_t apr_dir_entry_ftype(apr_filetype_e *type, apr_dir_t *thedir)
-{
-    int rc;
-    HFILE hFile;
-    ULONG action, Type, Attr;
-    apr_filetype_e typemap[8] = { APR_REG, APR_CHR, APR_PIPE };
-
-    if (thedir->validentry) {
-        if (thedir->entry.attrFile & FILE_DIRECTORY) {
-            *type = APR_DIR;
-            return APR_SUCCESS;
-        } else {
-            rc = DosOpen(apr_pstrcat(thedir->cntxt, thedir->dirname, "/", 
thedir->entry.achName, NULL) ,
-                         &hFile, &action, 0, 0,
-                         OPEN_ACTION_FAIL_IF_NEW|OPEN_ACTION_OPEN_IF_EXISTS, 
OPEN_SHARE_DENYNONE|OPEN_ACCESS_READONLY,
-                         NULL);
-
-            if ( rc == 0 ) {
-                rc = DosQueryHType( hFile, &Type, &Attr );
-
-                if ( rc == 0 ) {
-            *type = typemap[(Type & 0x0007)];
-                }
-                DosClose( hFile );
-            }
-
-            return APR_OS2_STATUS(rc);
-        }
-    }
-
-    return APR_ENOFILE;
-}
-
-
-
-apr_status_t apr_get_dir_filename(const char **new, apr_dir_t *thedir)
-{
-    if (thedir->validentry) {
-        *new = thedir->entry.achName;
-        return APR_SUCCESS;
-    }
-
-    return APR_ENOFILE;
-}
Index: srclib/apr/file_io/unix/dir.c
===================================================================
RCS file: /home/cvs/apr/file_io/unix/dir.c,v
retrieving revision 1.42
diff -u -r1.42 dir.c
--- srclib/apr/file_io/unix/dir.c       2001/01/05 19:40:05     1.42
+++ srclib/apr/file_io/unix/dir.c       2001/01/23 02:17:04
@@ -95,7 +95,7 @@
     }
 }
 
-apr_status_t apr_closedir(apr_dir_t *thedir)
+apr_status_t apr_dir_close(apr_dir_t *thedir)
 {
     apr_status_t rv;
 
@@ -106,36 +106,65 @@
     return rv;
 }
 
-apr_status_t apr_readdir(apr_dir_t *thedir)
+apr_status_t apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted,
+                          apr_dir_t *thedir)
 {
-#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \
-    && !defined(READDIR_IS_THREAD_SAFE)
     apr_status_t ret;
-#endif
-
 #if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \
     && !defined(READDIR_IS_THREAD_SAFE)
+    dirent *retent;
+
+    ret = readdir_r(thedir->dirstruct, thedir->entry, &retent);
 
-    ret = readdir_r(thedir->dirstruct, thedir->entry, &thedir->entry);
     /* Avoid the Linux problem where at end-of-directory thedir->entry
      * is set to NULL, but ret = APR_SUCCESS.
      */
-    return (ret == APR_SUCCESS && thedir->entry == NULL) ? APR_ENOENT : ret;
+    if(!ret || thedir->entry != retent)
+        ret = APR_ENOENT;
 #else
-
     thedir->entry = readdir(thedir->dirstruct);
     if (thedir->entry == NULL) {
         /* If NULL was returned, this can NEVER be a success. Can it?! */
         if (errno == APR_SUCCESS) {
-            return APR_ENOENT;
+            ret = APR_ENOENT;
         }
-        return errno;
+        else
+            ret = errno;
     }
-    return APR_SUCCESS;
 #endif
+
+    if (ret) {
+        finfo->valid = 0;
+        return ret;
+    }
+
+    /* What we already know */
+    /* FreeBSD can grab entry->d_type for APR_FINFO_TYPE as well */
+    wanted &= ~(APR_FINFO_NAME | APR_FINFO_INODE);
+    if (wanted)
+    {
+        char fspec[_MAXPATH];
+        int off;
+        apr_strcpyn(fspec, sizeof(fspec), thedir->dirname);
+        off = strlen(fspec);
+        if (fspec[off - 1] != '/')
+            fspec[off++] = '/';
+        apr_strcpyn(fspec + off, sizeof(fspec) - off, thedir->entry->d_name);
+        /* ??? Or lstat below? */
+        ret = apr_stat(finfo, wanted, fspec, thedir->cntxt);
+    }
+    if (!wanted || ret) {
+        finfo->cntxt = thedir->cntxt;
+        finfo->valid = 0;
+    }
+    finfo->valid |= APR_FINFO_INODE | APR_FINFO_NAME;
+    /* XXX: Is d_fileno consistent across platforms? */
+    finfo->inode = thedir->entry->d_fileno;
+    finfo->name = thedir->entry->d_name;
+    return APR_SUCCESS;
 }
 
-apr_status_t apr_rewinddir(apr_dir_t *thedir)
+apr_status_t apr_dir_rewind(apr_dir_t *thedir)
 {
     rewinddir(thedir->dirstruct);
     return APR_SUCCESS;
@@ -161,94 +190,6 @@
     else {
         return errno;
     }
-}
-
-apr_status_t apr_dir_entry_size(apr_size_t *size, apr_dir_t *thedir)
-{
-    struct stat filestat;
-    char *fname = NULL;    
-
-    if (thedir->entry == NULL) {
-        *size = -1;
-        return APR_ENOFILE;
-    }
-    fname = apr_pstrcat(thedir->cntxt, thedir->dirname, "/", 
-                       thedir->entry->d_name, NULL);
-    if (stat(fname, &filestat) == -1) {
-        *size = 0;
-        return errno;
-    }
-    
-    *size = filestat.st_size;
-    return APR_SUCCESS;
-}
-
-apr_status_t apr_dir_entry_mtime(apr_time_t *mtime, apr_dir_t *thedir)
-{
-    struct stat filestat;
-    char *fname = NULL;
-
-    if (thedir->entry == NULL) {
-        *mtime = -1;
-        return APR_ENOFILE;
-    }
-
-    fname = apr_pstrcat(thedir->cntxt, thedir->dirname, "/", 
-                       thedir->entry->d_name, NULL);
-    if (stat(fname, &filestat) == -1) {
-        *mtime = -1;
-        return errno;
-    }
-    
-    apr_ansi_time_to_apr_time(mtime, filestat.st_mtime);
-    return APR_SUCCESS;
-}
- 
-apr_status_t apr_dir_entry_ftype(apr_filetype_e *type, apr_dir_t *thedir)
-{
-    struct stat filestat;
-    char *fname = NULL;
-
-    if (thedir->entry == NULL) {
-        *type = APR_REG;
-        return APR_ENOFILE;
-    }
-
-    fname = apr_pstrcat(thedir->cntxt, thedir->dirname, "/", 
-                       thedir->entry->d_name, NULL);
-    if (stat(fname, &filestat) == -1) {
-        *type = APR_REG;
-        return errno;
-    }
-
-    if (S_ISREG(filestat.st_mode))
-        *type = APR_REG;    
-    if (S_ISDIR(filestat.st_mode))
-        *type = APR_DIR;    
-    if (S_ISCHR(filestat.st_mode))
-        *type = APR_CHR;    
-    if (S_ISBLK(filestat.st_mode))
-        *type = APR_BLK;    
-    if (S_ISFIFO(filestat.st_mode))
-        *type = APR_PIPE;    
-    if (S_ISLNK(filestat.st_mode))
-        *type = APR_LNK;    
-#ifndef BEOS
-    if (S_ISSOCK(filestat.st_mode))
-        *type = APR_SOCK;    
-#endif
-    return APR_SUCCESS;
-}
-
-apr_status_t apr_get_dir_filename(const char **new, apr_dir_t *thedir)
-{
-    /* Detect End-Of-File */
-    if (thedir == NULL || thedir->entry == NULL) {
-        *new = NULL;
-        return APR_ENOENT;
-    }
-    (*new) = thedir->entry->d_name;
-    return APR_SUCCESS;
 }
 
 apr_status_t apr_get_os_dir(apr_os_dir_t **thedir, apr_dir_t *dir)
Index: srclib/apr/file_io/unix/filestat.c
===================================================================
RCS file: /home/cvs/apr/file_io/unix/filestat.c,v
retrieving revision 1.37
diff -u -r1.37 filestat.c
--- srclib/apr/file_io/unix/filestat.c  2001/01/22 00:59:26     1.37
+++ srclib/apr/file_io/unix/filestat.c  2001/01/23 02:17:04
@@ -93,10 +93,7 @@
     finfo->size = info.st_size;
     finfo->inode = info.st_ino;
     finfo->device = info.st_dev;
-
-/* We don't have nlinks in the finfo structure.  Are we going to add it? RBB*/
-/*        finfo->nlinks = info.st_nlink;  */
-
+    finfo->nlink = info.st_nlink;
     apr_ansi_time_to_apr_time(&finfo->atime, info.st_atime);
     apr_ansi_time_to_apr_time(&finfo->mtime, info.st_mtime);
     apr_ansi_time_to_apr_time(&finfo->ctime, info.st_ctime);
Index: srclib/apr/file_io/win32/dir.c
===================================================================
RCS file: /home/cvs/apr/file_io/win32/dir.c,v
retrieving revision 1.43
diff -u -r1.43 dir.c
--- srclib/apr/file_io/win32/dir.c      2001/01/20 21:39:03     1.43
+++ srclib/apr/file_io/win32/dir.c      2001/01/23 02:17:04
@@ -129,7 +129,7 @@
     return APR_SUCCESS;
 }
 
-APR_DECLARE(apr_status_t) apr_closedir(apr_dir_t *dir)
+APR_DECLARE(apr_status_t) apr_dir_close(apr_dir_t *dir)
 {
     if (dir->dirhand != INVALID_HANDLE_VALUE && !FindClose(dir->dirhand)) {
         return apr_get_os_error();
@@ -138,7 +138,8 @@
     return APR_SUCCESS;
 }
 
-APR_DECLARE(apr_status_t) apr_readdir(apr_dir_t *thedir)
+APR_DECLARE(apr_status_t) apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted,
+                                       apr_dir_t *thedir)
 {
     /* The while loops below allow us to skip all invalid file names, so that
      * we aren't reporting any files where their absolute paths are too long.
@@ -147,6 +148,7 @@
     apr_oslevel_e os_level;
     if (!apr_get_oslevel(thedir->cntxt, &os_level) && os_level >= APR_WIN_NT)
     {
+        apr_status_t rv;
         if (thedir->dirhand == INVALID_HANDLE_VALUE) 
         {
             apr_wchar_t wdirname[8192];
@@ -171,6 +173,10 @@
                 return apr_get_os_error();
             }
         }
+        if (rv = unicode_to_utf8_path(thedir->name, MAX_PATH * 3 + 1, 
+                                      thedir->w.entry->cFileName))
+            return rv;
+        finfo->name = thedir->name;
     }
     else
 #endif
@@ -192,11 +198,31 @@
                 return apr_get_os_error();
             }
         }
+        finfo->name = thedir->n.entry->cFileName;
+    }
+    
+    finfo->size = (thedir->n.entry->nFileSizeHigh * MAXDWORD) + 
+                  thedir->n.entry->nFileSizeLow;
+    FileTimeToAprTime(&finfo->mtime, &thedir->n.entry->ftLastWriteTime);
+    switch(thedir->n.entry->dwFileAttributes) {
+        case FILE_ATTRIBUTE_DIRECTORY: {
+            finfo->filetype = APR_DIR;
+            return APR_SUCCESS;
+        }
+        case FILE_ATTRIBUTE_NORMAL: {
+            finfo->filetype = APR_REG;
+            return APR_SUCCESS;
+        }
+        default: {
+            finfo->filetype = APR_REG;     /* As valid as anything else.*/
+            return APR_SUCCESS;
+        }
     }
+
     return APR_SUCCESS;
 }
 
-APR_DECLARE(apr_status_t) apr_rewinddir(apr_dir_t *dir)
+APR_DECLARE(apr_status_t) apr_dir_rewind(apr_dir_t *dir)
 {
     dir_cleanup(dir);
     if (!FindClose(dir->dirhand)) {
@@ -255,65 +281,11 @@
     return APR_SUCCESS;
 }
 
-APR_DECLARE(apr_status_t) apr_dir_entry_size(apr_ssize_t *size,
-                                             apr_dir_t *thedir)
-{
-    if (thedir == NULL || thedir->n.entry == NULL) {
-        return APR_ENODIR;
-    }
-    (*size) = (thedir->n.entry->nFileSizeHigh * MAXDWORD) + 
-        thedir->n.entry->nFileSizeLow;
-    return APR_SUCCESS;
-}
 
-APR_DECLARE(apr_status_t) apr_dir_entry_mtime(apr_time_t *time,
-                                              apr_dir_t *thedir)
-{
-    if (thedir == NULL || thedir->n.entry == NULL) {
-        return APR_ENODIR;
-    }
-    FileTimeToAprTime(time, &thedir->n.entry->ftLastWriteTime);
-    return APR_SUCCESS;
-}
- 
-APR_DECLARE(apr_status_t) apr_dir_entry_ftype(apr_filetype_e *type,
-                                              apr_dir_t *thedir)
-{
-    switch(thedir->n.entry->dwFileAttributes) {
-        case FILE_ATTRIBUTE_DIRECTORY: {
-            (*type) = APR_DIR;
-            return APR_SUCCESS;
-        }
-        case FILE_ATTRIBUTE_NORMAL: {
-            (*type) = APR_REG;
-            return APR_SUCCESS;
-        }
-        default: {
-            (*type) = APR_REG;     /* As valid as anything else.*/
-            return APR_SUCCESS;
-        }
-    }
-}
 
-APR_DECLARE(apr_status_t) apr_get_dir_filename(const char **new,
-                                               apr_dir_t *thedir)
-{
-#if APR_HAS_UNICODE_FS
-    apr_oslevel_e os_level;
-    if (!apr_get_oslevel(thedir->cntxt, &os_level) && os_level >= APR_WIN_NT)
-    {
-        apr_status_t rv;
-        if (rv = unicode_to_utf8_path(thedir->name, MAX_PATH * 3 + 1, 
-                                      thedir->w.entry->cFileName))
-            return rv;
-        (*new) = thedir->name;
-    }
-    else
-#endif
-        (*new) = thedir->n.entry->cFileName;
-    return APR_SUCCESS;
-}
 
+
+
 APR_DECLARE(apr_status_t) apr_get_os_dir(apr_os_dir_t **thedir,
                                          apr_dir_t *dir)
 {
@@ -324,26 +296,9 @@
     return APR_SUCCESS;
 }
 
-/* XXX: This is sort of blinkin stupid on win32... consider,
- * our open doesn't open the dir, it sets up the apr_dir_t,
- * and on the first apr_readdir it actually does a FindFirstFile
- * if the handle is closed, or else a FindNextFile that is based 
- * on cached info that we simply don't have our hands on when
- * we use this function.  Maybe APR_ENOTIMPL would be better?
- */
 APR_DECLARE(apr_status_t) apr_put_os_dir(apr_dir_t **dir,
                                          apr_os_dir_t *thedir,
                                          apr_pool_t *cont)
 {
-    if (cont == NULL) {
-        return APR_ENOPOOL;
-    }
-    if ((*dir) == NULL) {
-        (*dir) = (apr_dir_t *)apr_pcalloc(cont, sizeof(apr_dir_t));
-        (*dir)->cntxt = cont;
-    }
-    else
-        (*dir)->rootlen = 0; /* We don't know, don't care */
-    (*dir)->dirhand = thedir;
-    return APR_SUCCESS;
+    return APR_ENOTIMPL;
 }
Index: srclib/apr/include/arch/os2/fileio.h
===================================================================
RCS file: /home/cvs/apr/include/arch/os2/fileio.h,v
retrieving revision 1.22
diff -u -r1.22 fileio.h
--- srclib/apr/include/arch/os2/fileio.h        2000/08/06 14:55:54     1.22
+++ srclib/apr/include/arch/os2/fileio.h        2001/01/23 02:17:05
@@ -63,6 +63,7 @@
 #include "apr_general.h"
 #include "apr_lock.h"
 #include "apr_file_io.h"
+#include "apr_file_info.h"
 #include "apr_errno.h"
 
 #define APR_FILE_BUFSIZE 4096
Index: srclib/apr/include/arch/unix/fileio.h
===================================================================
RCS file: /home/cvs/apr/include/arch/unix/fileio.h,v
retrieving revision 1.29
diff -u -r1.29 fileio.h
--- srclib/apr/include/arch/unix/fileio.h       2001/01/20 21:39:04     1.29
+++ srclib/apr/include/arch/unix/fileio.h       2001/01/23 02:17:05
@@ -60,6 +60,7 @@
 #include "apr_general.h"
 #include "apr_tables.h"
 #include "apr_file_io.h"
+#include "apr_file_info.h"
 #include "apr_errno.h"
 #include "apr_lib.h"
 
Index: srclib/apr/include/arch/win32/fileio.h
===================================================================
RCS file: /home/cvs/apr/include/arch/win32/fileio.h,v
retrieving revision 1.40
diff -u -r1.40 fileio.h
--- srclib/apr/include/arch/win32/fileio.h      2001/01/20 21:39:04     1.40
+++ srclib/apr/include/arch/win32/fileio.h      2001/01/23 02:17:06
@@ -62,6 +62,7 @@
 #include "apr_tables.h"
 #include "apr_lock.h"
 #include "apr_file_io.h"
+#include "apr_file_info.h"
 #include "apr_errno.h"
 #include "misc.h"
 
Index: srclib/apr/test/testfile.c
===================================================================
RCS file: /home/cvs/apr/test/testfile.c,v
retrieving revision 1.24
diff -u -r1.24 testfile.c
--- srclib/apr/test/testfile.c  2001/01/15 19:19:24     1.24
+++ srclib/apr/test/testfile.c  2001/01/23 02:17:10
@@ -290,8 +290,7 @@
     apr_dir_t *temp;  
     apr_file_t *file = NULL;
     apr_size_t bytes;
-    apr_filetype_e type;
-    const char *fname;
+    apr_finfo_t dirent;
 
     fprintf(stdout, "Testing Directory functions.\n");
 
@@ -322,7 +321,7 @@
     }
 
     fprintf(stdout, "\tReading Directory.......");
-    if ((apr_readdir(temp))  != APR_SUCCESS) {
+    if ((apr_dir_read(&dirent, APR_FINFO_DIRENT, temp))  != APR_SUCCESS) {
         fprintf(stderr, "Could not read directory\n");
         return -1;
     }
@@ -336,40 +335,39 @@
         /* Because I want the file I created, I am skipping the "." and ".."
          * files that are here. 
          */
-        if (apr_readdir(temp) != APR_SUCCESS) {
+        if (apr_dir_read(&dirent, APR_FINFO_DIRENT | APR_FINFO_TYPE
+                                | APR_FINFO_SIZE | APR_FINFO_MTIME, 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);
+    } while (dirent.name[0] == '.');
+    if (strcmp(dirent.name, "testfile")) {
+        fprintf(stderr, "Got wrong file name %s\n", dirent.name);
         return -1;
     }
     fprintf(stdout, "OK\n");
 
     fprintf(stdout, "\t\tFile type.......");
-    apr_dir_entry_ftype(&type, temp);
-    if (type != APR_REG) {
+    if (dirent.filetype != 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 %" APR_SIZE_T_FMT "\n", bytes);
+    if (dirent.size != bytes)) {
+        fprintf(stderr, "Got wrong file size %" APR_SIZE_T_FMT "\n", 
dirent.size);
         return -1;
     }
     fprintf(stdout, "OK\n");
      
     fprintf(stdout, "\tRewinding directory.......");
-    apr_rewinddir(temp); 
+    apr_dir_rewind(temp); 
     fprintf(stdout, "OK\n");
     
     fprintf(stdout, "\tClosing Directory.......");
-    if (apr_closedir(temp)  != APR_SUCCESS) {
+    if (apr_dir_close(temp)  != APR_SUCCESS) {
         fprintf(stderr, "Could not close directory\n");
         return -1;
     }

Reply via email to