apr_os_dir_put doesn't create a working apr_dir_t i.e. apr_dir_read will not work on the created apr_dir_t

This is not the case with apr_os_file_put which does in fact create a working apr_file_t

Is this a bug or a feature? There doesn't seem to be any users of apr_os_dir_put in the httpd tree.

Here is an example from my privilege separated wrapper functions for apr file io:

The apr_file_open wrapper is quite simple as the apr_os_file_put works as expected:

static apr_status_t privsep_file_open(privsep_token_t *token,
apr_file_t **new, const char *fname, apr_int32_t flag, apr_fileperms_t perm, apr_pool_t *pool)
{
   privsep_message_t msg;
   apr_os_file_t fd;

   if(!privsep_inited || !token)
     return apr_file_open(new, fname, flag, perm, pool);

   memset(&msg, 0, sizeof(msg));
   msg.command = privsep_command_file_open;
   msg.flags = flag;
   msg.perms = perm;
   fd = privsep_send_request(&msg, token, fname);

   if (msg.retval != APR_SUCCESS)
       return msg.retval;

   return apr_os_file_put(new, &fd, flag, pool);
}


But I have to resort to ugly hacks in my apr_dir_open implementation:

static apr_status_t privsep_dir_open(privsep_token_t *token,
apr_dir_t **new, const char *dirname, apr_pool_t *pool)
{
   privsep_message_t msg;
   apr_os_file_t fd;
   DIR *dir;

   if(!privsep_inited || !token)
     return apr_dir_open(new, dirname, pool);

   memset(&msg, 0, sizeof(msg));
   msg.command = privsep_command_dir_open;
   fd = privsep_send_request(&msg, token, dirname);

   if (msg.retval != APR_SUCCESS)
       return msg.retval;

   /* apr_os_dir_put does not create a fullly allocated apr_dir_t
      so we need to open a directory to create one then replace
      the fd in the associated apr_os_dir */
   if(apr_dir_open(new, "/", pool) != APR_SUCCESS) {
        close(fd);
        return APR_EGENERAL;
   }

   /* Ok, now the nasty bit:
Here we assume that an integer file descriptor is the first element of the opaque DIR structure pointed at by dir
      This is the case on Linux, FreeBSD, Mac OS X and Solaris */
   apr_os_dir_get(&dir, *new);
close(*(int *)dir); *(int *)dir = fd;
   (*new)->dirname = apr_pstrdup(pool, dirname);
   return apr_os_dir_put(new, dir, pool);
}



Reply via email to