Tom Lane wrote:
> Bruce Momjian <[EMAIL PROTECTED]> writes:
> > Tom Lane wrote:
> >> I guess what you are saying is we should have a configure-time option to
> >> address configured directories via relative paths from the executable's
> >> directory, rather than absolute paths?  Seems reasonable ...
> 
> > Yep.  In fact, why would we not use that by default?
> 
> Because it'll be slower.  Instead of
>       /usr/local/pgsql/lib
> we'd be using something like
>       /usr/local/pgsql/bin/../lib
> which is not too bad here but would get worse if the directories are not
> so close.
> 
> But perhaps we can arrange for the path to be simplified down to an
> absolute form when it's constructed at backend startup?  You'd need a
> routine anyway to combine the bindir path (determined by FindExec) with
> the relative path provided by configure, so maybe this routine could be
> smart about leading ../ in the configure path.

I wrote relative_path() which does the mapping from compiled src/dst to
a new path.  For example:

        $ tst1 /usr/local/pgsql/bin /usr/local/pgsql/lib /users/fred/pgsql/bin
        /users/fred/pgsql/lib

        $ tst1 /a/b/c /a/d /f/g/h
        /f/d

This can be used in the backend to map from your bindir to a relative
libdir at runtime, and share too.  It returns [mp]alloc'ed values, or
NULL if it can't do the tranformation.

Patch attached.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  [EMAIL PROTECTED]               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: src/include/port.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/port.h,v
retrieving revision 1.27
diff -c -c -r1.27 port.h
*** src/include/port.h  30 Apr 2004 17:52:07 -0000      1.27
--- src/include/port.h  4 May 2004 17:07:30 -0000
***************
*** 26,31 ****
--- 26,32 ----
  extern char *last_path_separator(const char *filename);
  extern void canonicalize_path(char *path);
  extern char *get_progname(char *argv0);
+ extern char *relative_path(const char *src, const char *dst, const char *target);
  
  /* Portable delay handling */
  extern void pg_usleep(long microsec);
Index: src/port/path.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/port/path.c,v
retrieving revision 1.5
diff -c -c -r1.5 path.c
*** src/port/path.c     9 Mar 2004 04:49:02 -0000       1.5
--- src/port/path.c     4 May 2004 17:07:31 -0000
***************
*** 13,21 ****
--- 13,31 ----
   *-------------------------------------------------------------------------
   */
  
+ #ifndef FRONTEND
+ #include "postgres.h"
+ #else
  #include "c.h"
+ #endif
  #include <ctype.h>
  
+ #ifndef WIN32
+ #define ISSEP(c)      ((c) == '/')
+ #else
+ #define ISSEP(c)      ((c) == '/' || (c) == '\\')
+ #endif
+ 
  /*
   *    is_absolute_path
   */
***************
*** 33,39 ****
  }
  
  
- 
  /*
   *    first_path_separator
   */
--- 43,48 ----
***************
*** 120,123 ****
--- 129,241 ----
                return argv0;
        else
                return last_path_separator(argv0) + 1;
+ }
+ 
+ 
+ /*
+  *    relative_path
+  *
+  *    Determine the relative path for getting from 'src' to 'dst' and
+  *    map that change from 'target' to a new directory.
+  */
+ char *
+ relative_path(const char *src, const char *dst, const char *target)
+ {
+       const char *dst_slash = NULL;
+       char    *ret;
+       int             dirs_up;
+       
+ #ifdef WIN32
+       if (isalpha(*src) && src[1] == ':' &&
+               isalpha(*dst) && dst[1] == ':')
+       {
+               if (toupper(*src) != toupper(*src))
+                       return NULL;    /* no relative path, can't cross drive letters 
*/
+       }
+ 
+       /* Move past drive letters */
+       if (isalpha(*src) && src[1] == ':')
+               src += 2;
+       if (isalpha(*dst) && dst[1] == ':')
+               src += 2;
+ #endif
+ 
+       /* If we don't have two absolute paths, give up */
+       if (!is_absolute_path(src) ||
+               !is_absolute_path(dst))
+               return NULL;
+ 
+       dst_slash = dst;
+ 
+       while (1)
+       {
+               /* Move past adjacent slashes like //, and trailing ones */
+               while (ISSEP(*src) && (ISSEP(src[1]) || !src[1]))
+                       src++;
+               while (ISSEP(*dst) && (ISSEP(dst[1]) || !dst[1]))
+                       dst++;
+ 
+               /* Paths are done or not equal? */
+               if (!*src || !*dst)
+                       break;
+ #ifndef WIN32
+               if (*src != *dst)
+                       break;
+ #else
+               /* Win32 filesystem is case insensitive */
+               if (toupper(*src) != toupper(*dst) &&
+                       (!ISSEP(*src) || !ISSEP(*dst))) /* '/' == '\\' */
+                       break;
+ #endif
+               if (ISSEP(*dst))
+                       dst_slash = dst;
+ 
+               src++;
+               dst++;
+       }
+ 
+       /* Did the last part of the path match? */
+       dirs_up = ((*src == '\0' || ISSEP(*src)) &&
+                          (*dst == '\0' || ISSEP(*dst))) ? 0 : 1;
+ 
+       /* How many directories do we have to move up? */
+       while (*src)
+       {
+               if (ISSEP(*src))
+               {
+                       while (ISSEP(*src))
+                               src++;
+                       if (*src != '\0')       /* skip trailing slash */
+                               dirs_up++;
+               }
+               else
+                       src++;
+       }
+               
+ #ifndef FRONTEND
+       ret = palloc(strlen(target) + strlen(dst) + 1);
+ #else
+       ret = malloc(strlen(target) + strlen(dst) + 1);
+ #endif
+ 
+       strcpy(ret, target);
+ 
+       /* Trim off trailing slash from target */
+       if (strlen(ret) > 0 && ISSEP(ret[strlen(ret)-1]))
+               dirs_up++;
+               
+       while (dirs_up--)
+               if (last_path_separator(ret) != NULL)
+                       *last_path_separator(ret) = '\0';       /* trim off directory 
*/
+               else
+                       return NULL;
+ 
+       /* Add dst to trimmed target */
+       strcat(ret, dst_slash);
+       
+       /* Trim off trailing slash from result */
+       if (strlen(ret) > 0 && ISSEP(ret[strlen(ret)-1]))
+               *last_path_separator(ret) = '\0';       /* trim off slash */
+ 
+       return ret;
  }
---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
    (send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])

Reply via email to