home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 2.ddi / CLIBSRC3.ZIP / FULLPATH.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  6.9 KB  |  204 lines

  1. /*-----------------------------------------------------------------------*
  2.  * filename - fullpath.c
  3.  *
  4.  * function(s)
  5.  *        isSlash   - check for directory separator character
  6.  *        _fullpath - make an absolute path name from a relative path name
  7.  *-----------------------------------------------------------------------*/
  8.  
  9. /*
  10.  *      C/C++ Run Time Library - Version 5.0
  11.  *
  12.  *      Copyright (c) 1987, 1992 by Borland International
  13.  *      All Rights Reserved.
  14.  *
  15.  */
  16.  
  17.  
  18. #include <ctype.h>
  19. #include <direct.h>
  20. #include <dos.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23.  
  24. /*---------------------------------------------------------------------*
  25.  
  26. Name            isSlash - check for directory separator character
  27.  
  28. Usage           int isSlash(int c);
  29.  
  30. Prototype in    local
  31.  
  32. Description     isSlash returns true if the character c is a valid
  33.                 directory separator character (\ or / on DOS, / on UNIX).
  34.                 It returns false otherwise.
  35.  
  36. Return value    Describe above.
  37.  
  38. *---------------------------------------------------------------------*/
  39. static int pascal near isSlash (int c)
  40. {
  41.     return (c == '\\' || c == '/');
  42. }
  43.  
  44. /*---------------------------------------------------------------------*
  45.  
  46. Name            _fullpath - makes new file name
  47.  
  48. Usage           #include <dir.h>
  49.                 char *_fullpath(char *buffer, const char * pathname,
  50.                                 size_t maxlen);
  51.  
  52. Prototype in    stdlib.h
  53.  
  54. Description     _fullpath converts the relative path name name 'pathname'
  55.                 to a fully qualified pathname, stored in 'buffer'.  The
  56.                 relative path can contain ".\" and "..".
  57.  
  58.                 The maximum size of the supplied buffer is 'maxlen'.
  59.                 If the fully qualified path is longer than 'maxlen',
  60.                 NULL is returned.  The buffer should be at least _MAX_PATH
  61.                 bytes long (this constant is defined in stdlib.h).
  62.  
  63.                 If 'buffer' is NULL, a buffer to store the fully qualified
  64.                 path is allocated and is returned.  The calling program
  65.                 must free this buffer with free() when it is no longer needed.
  66.  
  67.                 If the pathname does not specify a disk drive, the current
  68.                 drive is used.
  69.  
  70. Return value    A pointer to the buffer containing the fully qualified
  71.                 path is returned.  If there is an error, NULL is returned.
  72.  
  73. Note            This function is a rewrite of the FExpand procedure
  74.                 in the Turbo Pascal RTL, with modifications for MSC
  75.                 compatibility.
  76.  
  77. *---------------------------------------------------------------------*/
  78. char * _CType _FARFUNC _fullpath(char *buffer,
  79.                                  const char *pathname,
  80.                                  size_t maxlen
  81.                                 )
  82. {
  83.     char *tempbuf;
  84.     char *dst, *src;
  85.     int c, len, driveletter;
  86.     unsigned drive;
  87.  
  88.     /* Allocate a temporary buffer to hold the fully qualified path.
  89.      */
  90.     if ((tempbuf = malloc(_MAX_PATH*2+1)) == NULL)
  91.         return (NULL);
  92.  
  93.     /* Check for a drive name.  If one is not provided,
  94.      * get the current drive.  Point src at the first
  95.      * character in pathname after the drive name, if any.
  96.      */
  97.     src = (char *)pathname;
  98.     if (isalpha(src[0]) && src[1] == ':')
  99.         {
  100.         drive = toupper(driveletter = src[0]) - 'A' + 1;
  101.         src += 2;
  102.         }
  103.     else
  104.         {
  105.         _dos_getdrive(&drive);          /* get current drive */
  106.         driveletter = drive + 'A' - 1;
  107.         }
  108.  
  109.     /* If supplied path is relative, append it to the drivename
  110.      * and its current directory.  Otherwise append it to the
  111.      * drivename only.
  112.      */
  113.     if (!isSlash(src[0]))               /* path is relative? */
  114.         {
  115.         /* Get drivename and its current directory.
  116.          */
  117.         if (_getdcwd(drive,tempbuf,_MAX_PATH*2+1) == NULL)
  118.             {
  119.             free(tempbuf);
  120.             return (NULL);
  121.             }
  122.         dst = &tempbuf[strlen(tempbuf)];
  123.         if (!isSlash(*(dst-1)))         /* if directory doesn't end in slash */
  124.             *dst++ = '\\';              /* append one */
  125.         }
  126.     else
  127.         {
  128.         /* Path is absolute.  Store the drivename only.
  129.          */
  130.         dst = tempbuf;
  131.         *dst++ = driveletter;
  132.         *dst++ = ':';
  133.         }
  134.     strcpy(dst,src);                    /* concatenate supplied path */
  135.  
  136.     /* Scan the path, squeezing out "..\" and ".\", and
  137.      * squeezing out the previous directory when "..\" is found.
  138.      */
  139.     src = dst = tempbuf;
  140.     for (;;)
  141.         {
  142.         /* If this the end of the path, or end of a directory,
  143.          * we must check for "." or ".."
  144.          */
  145.         if ((c = *src++) == '\0' || isSlash(c))
  146.             {
  147.             /* If last directory copied was "\.", back up over it.
  148.              */
  149.             if (*(dst-1) == '.' && isSlash(*(dst-2)))
  150.                 dst -= 2;
  151.  
  152.             /* If last directory copied was "\..", back up over it
  153.              * AND the previous directory.
  154.              */
  155.             else if (*(dst-1) == '.' && *(dst-2) == '.' && isSlash(*(dst-3)))
  156.                 {
  157.                 dst -= 3;               /* back up over "\.." */
  158.                 if (*(dst-1) == ':')    /* can't back up over drivename */
  159.                     {
  160.                     free(tempbuf);
  161.                     return(NULL);
  162.                     }
  163.                 while (!isSlash(*--dst))
  164.                     ;                   /* back up to start of prev. dir. */
  165.                 }
  166.  
  167.             if (c == '\0')              /* end of path? */
  168.                 {
  169.                 if (isSlash(*(dst-1)))  /* if last char is slash */
  170.                     dst--;              /*  back up over it */
  171.                 if (*(dst-1) == ':')    /* if path is just a drivename */
  172.                     *dst++ = '\\';      /*  append a slash */
  173.                 *dst = '\0';            /* append null terminator */
  174.                 break;
  175.                 }
  176.             else
  177.                 *dst++ = c;             /* copy the slash */
  178.             }
  179.         else
  180.             *dst++ = c;                 /* copy the character */
  181.         }
  182.  
  183.     /* Copy the temp buffer to the user's buffer, if present.
  184.      * Otherwise shrink the temp buffer and return a pointer to it.
  185.      */
  186.     len = strlen(tempbuf) + 1;                  /* length of path and null */
  187.     if (buffer != NULL)
  188.         {
  189.         if (len > maxlen)                       /* user buffer too small? */
  190.             {
  191.             free(tempbuf);
  192.             return (NULL);
  193.             }
  194.         else
  195.             {
  196.             strcpy(buffer,tempbuf);
  197.             free(tempbuf);
  198.             return (buffer);
  199.             }
  200.         }
  201.     else
  202.         return (realloc(tempbuf,len));          /* shrink the buffer */
  203. }
  204.