apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r..@covalent.net
Subject New directory API...
Date Mon, 22 Jan 2001 02:56:52 GMT

Will Rowe and I were talking earlier today, and our directory API is
horribly broken and inefficient.  Basically, on Unix if you want to get
any information about a file in a directory, we have to do a stat for each
piece of information.

For example, if you want the size, that's one stat.  If you then want the
file type, that's another stat.  Yuck!

Here is a design that Will suggested earlier today, implemented for
Unix.  Basically, it just uses the finfo structure to store information
about the file when you read it from the directory.

? build.log
? build.err
Index: file_io/unix/dir.c
===================================================================
RCS file: /home/cvs/apr/file_io/unix/dir.c,v
retrieving revision 1.42
diff -u -d -b -w -u -r1.42 dir.c
--- file_io/unix/dir.c	2001/01/05 19:40:05	1.42
+++ file_io/unix/dir.c	2001/01/22 02:46:57
@@ -53,6 +53,7 @@
  */
 
 #include "fileio.h"
+#include "apr_file_info.h"
 #include "apr_strings.h"
 #include "apr_portable.h"
 
@@ -106,20 +107,18 @@
     return rv;
 }
 
-apr_status_t apr_readdir(apr_dir_t *thedir)
+apr_status_t apr_readdir(apr_finfo_t *finfo, 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)
 
     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.
      */
+    finfo->cntxt = thedir->cntxt;
+    finfo->fname = apr_pstrcat(thedir->cntxt, thedir->dirname, "/", thedir->entry->d_name,
NULL);
     return (ret == APR_SUCCESS && thedir->entry == NULL) ? APR_ENOENT : ret;
 #else
 
@@ -131,6 +130,8 @@
         }
         return errno;
     }
+    finfo->cntxt = thedir->cntxt;
+    finfo->fname = apr_pstrcat(thedir->cntxt, thedir->dirname, "/", thedir->entry->d_name,
NULL);
     return APR_SUCCESS;
 #endif
 }
@@ -161,94 +162,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: include/apr_file_info.h
===================================================================
RCS file: /home/cvs/apr/include/apr_file_info.h,v
retrieving revision 1.4
diff -u -d -b -w -u -r1.4 apr_file_info.h
--- include/apr_file_info.h	2001/01/20 22:18:55	1.4
+++ include/apr_file_info.h	2001/01/22 02:46:57
@@ -255,9 +255,9 @@
  * 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_readdir(apr_finfo_t *finfo, apr_dir_t *thedir)
  */                        
-APR_DECLARE(apr_status_t) apr_readdir(apr_dir_t *thedir);
+APR_DECLARE(apr_status_t) apr_readdir(apr_finfo_t *finfo, apr_dir_t *thedir);
 
 /**
  * Rewind the directory to the first entry.
@@ -265,42 +265,6 @@
  * @deffunc apr_status_t apr_rewinddir(apr_dir_t *thedir)
  */                        
 APR_DECLARE(apr_status_t) apr_rewinddir(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: test/testfile.c
===================================================================
RCS file: /home/cvs/apr/test/testfile.c,v
retrieving revision 1.24
diff -u -d -b -w -u -r1.24 testfile.c
--- test/testfile.c	2001/01/15 19:19:24	1.24
+++ test/testfile.c	2001/01/22 02:46:59
@@ -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 finfo;
 
     fprintf(stdout, "Testing Directory functions.\n");
 
@@ -322,7 +321,7 @@
     }
 
     fprintf(stdout, "\tReading Directory.......");
-    if ((apr_readdir(temp))  != APR_SUCCESS) {
+    if ((apr_readdir(&finfo, temp))  != APR_SUCCESS) {
         fprintf(stderr, "Could not read directory\n");
         return -1;
     }
@@ -336,29 +335,28 @@
         /* Because I want the file I created, I am skipping the "." and ".."
          * files that are here. 
          */
-        if (apr_readdir(temp) != APR_SUCCESS) {
+        if (apr_readdir(&finfo, 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 (!strncmp(finfo.fname, "testdir/.", strlen("testdir/.")));
+    if (strcmp(finfo.fname, "testdir/testfile")) {
+        fprintf(stderr, "Got wrong file name %s\n", finfo.fname);
         return -1;
     }
     fprintf(stdout, "OK\n");
 
+    apr_stat(&finfo, finfo.fname, APR_FINFO_NORM, finfo.cntxt);
+
     fprintf(stdout, "\t\tFile type.......");
-    apr_dir_entry_ftype(&type, temp);
-    if (type != APR_REG) {
+    if (finfo.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!!!")) {
+    if (finfo.size != strlen("Another test!!!")) {
         fprintf(stderr, "Got wrong file size %" APR_SIZE_T_FMT "\n", bytes);
         return -1;
     }


_______________________________________________________________________________
Ryan Bloom                        	rbb@apache.org
406 29th St.
San Francisco, CA 94131
-------------------------------------------------------------------------------


Mime
View raw message