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;
}