apr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From wr...@apache.org
Subject cvs commit: apr/file_io/unix filepath.c Makefile.in
Date Sat, 31 Mar 2001 06:22:38 GMT
wrowe       01/03/30 22:22:38

  Modified:    .        CHANGES
               include  apr_file_info.h
               file_io/unix Makefile.in
  Added:       file_io/unix filepath.c
  Log:
    First draft implementation of unix apr_filepath_ get, set, merge, and
    parse_root.  [William Rowe]
  
  Revision  Changes    Path
  1.77      +3 -0      apr/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/apr/CHANGES,v
  retrieving revision 1.76
  retrieving revision 1.77
  diff -u -r1.76 -r1.77
  --- CHANGES	2001/03/31 05:52:41	1.76
  +++ CHANGES	2001/03/31 06:22:37	1.77
  @@ -1,5 +1,8 @@
   Changes with APR b1  
   
  +  *) First draft implementation of apr_filepath (get/set/parse_root
  +     and merge) for Unix.  [William Rowe]
  +
     *) Add apr_ipsubnet_create() and apr_ipsubnet_test() for testing
        whether or not an address is within a subnet.  [Jeff Trawick]
   
  
  
  
  1.15      +41 -4     apr/include/apr_file_info.h
  
  Index: apr_file_info.h
  ===================================================================
  RCS file: /home/cvs/apr/include/apr_file_info.h,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- apr_file_info.h	2001/03/24 04:22:36	1.14
  +++ apr_file_info.h	2001/03/31 06:22:37	1.15
  @@ -291,6 +291,25 @@
    */
   #define APR_FILEPATH_TRUENAME       0x20
   
  +/**
  + * Extract the rootpath from the given filepath
  + * @param rootpath the root file path returned with APR_SUCCESS or APR_EINCOMPLETE
  + * @param filepath the pathname to parse for it's root component
  + * @param p the pool to allocate the new path string from
  + * @deffunc apr_status_t apr_filepath_root(const char **rootpath, const char **inpath,
apr_pool_t *p)
  + * @tip on return, filepath now points to the character following the root.
  + * In the simplest example, given a filepath of "/foo", returns the rootpath
  + * of "/" and filepath points at "foo".  This is far more complex on other 
  + * platforms, which even changes alternate format of rootpath to canonical
  + * form.  The function returns APR_ERELATIVE if filepath isn't rooted (an
  + * error), APR_EINCOMPLETE if the root path is ambigious (but potentially
  + * legitimate, e.g. "/" on Windows is incomplete because it doesn't specify
  + * the drive letter), or APR_EBADPATH if the root is simply invalid.
  + * APR_SUCCESS is returned if filepath is an absolute path.
  + */
  +APR_DECLARE(apr_status_t) apr_filepath_root(const char **rootpath, 
  +                                            const char **filepath, 
  +                                            apr_pool_t *p);
   
   /**
    * Merge additional file path onto the previously processed rootpath
  @@ -301,10 +320,28 @@
    * @param p the pool to allocate the new path string from
    * @deffunc apr_status_t apr_filepath_merge(char **newpath, const char *rootpath, const
char *addpath, apr_int32_t flags, apr_pool_t *p)
    */                        
  -APR_DECLARE(apr_status_t) 
  -                apr_filepath_merge(char **newpath, const char *rootpath,
  -                                   const char *addpath, apr_int32_t flags,
  -                                   apr_pool_t *p);
  +APR_DECLARE(apr_status_t) apr_filepath_merge(char **newpath, 
  +                                             const char *rootpath,
  +                                             const char *addpath, 
  +                                             apr_int32_t flags,
  +                                             apr_pool_t *p);
  +
  +/**
  + * Return the default file path (for relative file names)
  + * @param path the default path string returned
  + * @param p the pool to allocate the default path string from
  + * @deffunc apr_status_t apr_filepath_get(char **path, apr_pool_t *p)
  + */
  +APR_DECLARE(apr_status_t) apr_filepath_get(char **path, apr_pool_t *p);
  +
  +/**
  + * Set the default file path (for relative file names)
  + * @param path the default path returned
  + * @param p the pool to allocate any working storage
  + * @deffunc apr_status_t apr_filepath_get(char **defpath, apr_pool_t *p)
  + */
  +APR_DECLARE(apr_status_t) apr_filepath_set(const char *path, apr_pool_t *p);
  +
   
   #ifdef __cplusplus
   }
  
  
  
  1.23      +1 -0      apr/file_io/unix/Makefile.in
  
  Index: Makefile.in
  ===================================================================
  RCS file: /home/cvs/apr/file_io/unix/Makefile.in,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- Makefile.in	2001/02/21 15:51:42	1.22
  +++ Makefile.in	2001/03/31 06:22:38	1.23
  @@ -3,6 +3,7 @@
   	dir.lo \
   	fileacc.lo \
   	filedup.lo \
  +	filepath.lo \
   	filestat.lo \
   	flock.lo \
   	fullrw.lo \
  
  
  
  1.1                  apr/file_io/unix/filepath.c
  
  Index: filepath.c
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  #include "apr.h"
  #include "fileio.h"
  #include "apr_file_io.h"
  #include "apr_strings.h"
  #if APR_HAVE_UNISTD_H
  #include <unistd.h>
  #endif
  
  #include <direct.h>
  
  
  /* Any OS that requires/refuses trailing slashes should be delt with here.
   */
  APR_DECLARE(apr_status_t) apr_filepath_get(char **defpath, apr_pool_t *p)
  {
      char path[APR_PATH_MAX];
      if (!getcwd(path, sizeof(path))) {
          if (errno == ERANGE)
              return APR_ENAMETOOLONG;
          else
              return errno;
      }
      *defpath = apr_pstrdup(p, path);
      return APR_SUCCESS;
  }    
  
  
  /* Any OS that requires/refuses trailing slashes should be delt with here
   */
  APR_DECLARE(apr_status_t) apr_filepath_set(const char *path, apr_pool_t *p)
  {
      if (chdir(path) != 0)
          return errno;
      return APR_SUCCESS;
  }    
  
  
  APR_DECLARE(apr_status_t) apr_filepath_parse_root(const char **rootpath, 
                                                    const char **inpath,
                                                    apr_pool_t *p)
  {
      if (**inpath == '/') 
      {
          *rootpath = apr_pstrdup(p, "/");
          ++*inpath;
          return APR_EABSOLUTE;
      }
  
      return APR_ERELATIVE;
  }
  
  
  APR_DECLARE(apr_status_t) apr_filepath_merge(char **newpath, 
                                               const char *rootpath, 
                                               const char *addpath, 
                                               apr_int32_t flags,
                                               apr_pool_t *p)
  {
      char path[APR_PATH_MAX];
      apr_size_t rootlen; /* is the original rootpath len */
      apr_size_t newseg;  /* is the path offset to the added path */
      apr_size_t addseg;  /* is the path offset we are appending at */
      apr_size_t endseg;  /* is the end of the current segment */
      apr_status_t rv;
  
      /* Treat null as an empty path.
       */
      if (!addpath)
          addpath = "";
  
      if (addpath[0] == '/') 
      {
          /* If addpath is rooted, then rootpath is unused.
           * Ths violates any APR_FILEPATH_SECUREROOTTEST and
           * APR_FILEPATH_NOTABSOLUTE flags specified.
           */
          if (flags & APR_FILEPATH_SECUREROOTTEST)
              return APR_EABOVEROOT;
          if (flags & APR_FILEPATH_NOTABSOLUTE)
              return APR_EABSOLUTE;
  
          /* If APR_FILEPATH_NOTABOVEROOT wasn't specified,
           * we won't test the root again, it's ignored.
           * Waste no CPU retrieving the working path.
           */
          if (!rootpath && !(flags & APR_FILEPATH_NOTABOVEROOT))
              rootpath = "";
      }
      else 
      {
          /* If APR_FILEPATH_NOTABSOLUTE is specified, the caller 
           * requires a relative result.  If the rootpath is
           * ommitted, we do not retrieve the working path,
           * if rootpath was supplied as absolute then fail.
           */
          if (flags & APR_FILEPATH_NOTABSOLUTE) 
          {
              if (!rootpath)
                  rootpath = "";
              else if (rootpath[0] == '/')
                  return APR_EABSOLUTE;
          }
      }
  
      if (!rootpath) 
      {
          /* Start with the current working path.  This is bass akwards,
           * but required since the compiler (at least vc) doesn't like
           * passing the address of a char const* for a char** arg.
           */
          char *getpath;
          rv = apr_filepath_get(&getpath, p);
          rootpath = getpath;
          if (rv != APR_SUCCESS)
              return errno;
      
          /* XXX: Any kernel subject to goofy, uncanonical results
           * must run the rootpath against the user's given flags.
           * Simplest would be a recursive call to apr_filepath_merge
           * with an empty (not null) rootpath and addpath of the cwd.
           */
      }
  
      rootlen = strlen(rootpath);
  
      if (addpath[0] == '/') 
      {
          /* Ignore the given root path, strip off leading 
           * '/'s to a single leading '/' from the addpath,
           * and leave addpath at the first non-'/' character.
           */
          newseg = 0;
          while (addpath[0] == '/')
              ++addpath;
          strcpy (path, "/");
          addseg = 1;
      }
      else
      {
          /* If both paths are relative, fail early
           */
          if (rootpath[0] != '/' && (flags & APR_FILEPATH_NOTRELATIVE))
                  return APR_ERELATIVE;
  
          /* Base the result path on the rootpath
           */
          newseg = rootlen;
          if (rootlen >= sizeof(path))
              return APR_ENAMETOOLONG;
          strcpy(path, rootpath);
          
          /* Always '/' terminate the given root path
           */
          if (newseg && path[newseg - 1] != '/') {
              if (newseg + 1 >= sizeof(path))
                  return APR_ENAMETOOLONG;
              path[newseg++] = '/';
              path[newseg] = '\0';
          }
          addseg = newseg;
      }
  
      while (*addpath) 
      {
          /* Parse each segment, find the closing '/' 
           */
          endseg = 0;
          while (addpath[endseg] && addpath[endseg] != '/')
              ++endseg;
  
          if (endseg == 0 || (endseg == 1 && addpath[0] == '.')) 
          {
              /* noop segment (/ or ./) so skip it 
               */
          }
          else if (endseg == 2 && addpath[0] == '.' && addpath[1] == '.')

          {
              /* backpath (../) */
              if (addseg == 1 && path[0] == '/') 
              {
                  /* Attempt to move above root.  Always die if the 
                   * APR_FILEPATH_SECUREROOTTEST flag is specified.
                   */
                  if (flags & APR_FILEPATH_SECUREROOTTEST)
                      return APR_EABOVEROOT;
                  
                  /* Otherwise this is simply a noop, above root is root.
                   * Flag that rootpath was entirely replaced.
                   */
                  newseg = 0;
              }
              else if (addseg == 0 || (addseg >= 3 
                                    && strcmp(path + addseg - 3, "../") == 0)) 
              {
                  /* Path is already backpathed or empty, if the
                   * APR_FILEPATH_SECUREROOTTEST.was given die now.
                   */
                  if (flags & APR_FILEPATH_SECUREROOTTEST)
                      return APR_EABOVEROOT;
  
                  /* Otherwise append another backpath.
                   */
                  if (addseg + 3 >= sizeof(path))
                      return APR_ENAMETOOLONG;
                  strcpy(path + addseg, "../");
                  addseg += 3;
              }
              else 
              {
                  /* otherwise crop the prior segment 
                   */
                  do {
                      --addseg;
                  } while (addseg && path[addseg - 1] != '/');
                  path[addseg] = '\0';
              }
  
              /* Now test if we are above where we started and back up
               * the newseg offset to reflect the added/altered path.
               */
              if (addseg < newseg) 
              {
                  if (flags & APR_FILEPATH_SECUREROOTTEST)
                      return APR_EABOVEROOT;
                  newseg = addseg;
              }
          }
          else 
          {
              /* An actual segment, append it to the destination path
               */
              apr_size_t i = (addpath[endseg] != '\0');
              if (addseg + endseg + i >= sizeof(path))
                  return APR_ENAMETOOLONG;
              strncpy(path + addseg, addpath, endseg + i);
              addseg += endseg + i;
          }
  
          /* Skip over trailing slash to the next segment
           */
          if (addpath[endseg])
              ++endseg;
  
          addpath += endseg;
      }
  
      /* newseg will be the rootlen unless the addpath contained
       * backpath elements.  If so, and APR_FILEPATH_NOTABOVEROOT
       * is specified (APR_FILEPATH_SECUREROOTTEST was caught above),
       * compare the original root to assure the result path is
       * still within given root path.
       */
      if ((flags & APR_FILEPATH_NOTABOVEROOT) && newseg < rootlen) {
          if (strncmp(rootpath, path, rootlen))
              return APR_EABOVEROOT;
          if (rootpath[rootlen - 1] != '/'
                  && path[rootlen] && path[rootlen] != '/')
              return APR_EABOVEROOT;
      }
  
      *newpath = apr_pstrdup(p, path);
      return (newpath ? APR_SUCCESS : APR_ENOMEM);
  }
  
  

Mime
View raw message