home *** CD-ROM | disk | FTP | other *** search
- /*-----------------------------------------------------------------------*
- * filename - fullpath.c
- *
- * function(s)
- * isSlash - check for directory separator character
- * _fullpath - make an absolute path name from a relative path name
- *-----------------------------------------------------------------------*/
-
- /*
- * C/C++ Run Time Library - Version 5.0
- *
- * Copyright (c) 1987, 1992 by Borland International
- * All Rights Reserved.
- *
- */
-
-
- #include <ctype.h>
- #include <direct.h>
- #include <dos.h>
- #include <stdlib.h>
- #include <string.h>
-
- /*---------------------------------------------------------------------*
-
- Name isSlash - check for directory separator character
-
- Usage int isSlash(int c);
-
- Prototype in local
-
- Description isSlash returns true if the character c is a valid
- directory separator character (\ or / on DOS, / on UNIX).
- It returns false otherwise.
-
- Return value Describe above.
-
- *---------------------------------------------------------------------*/
- static int pascal near isSlash (int c)
- {
- return (c == '\\' || c == '/');
- }
-
- /*---------------------------------------------------------------------*
-
- Name _fullpath - makes new file name
-
- Usage #include <dir.h>
- char *_fullpath(char *buffer, const char * pathname,
- size_t maxlen);
-
- Prototype in stdlib.h
-
- Description _fullpath converts the relative path name name 'pathname'
- to a fully qualified pathname, stored in 'buffer'. The
- relative path can contain ".\" and "..".
-
- The maximum size of the supplied buffer is 'maxlen'.
- If the fully qualified path is longer than 'maxlen',
- NULL is returned. The buffer should be at least _MAX_PATH
- bytes long (this constant is defined in stdlib.h).
-
- If 'buffer' is NULL, a buffer to store the fully qualified
- path is allocated and is returned. The calling program
- must free this buffer with free() when it is no longer needed.
-
- If the pathname does not specify a disk drive, the current
- drive is used.
-
- Return value A pointer to the buffer containing the fully qualified
- path is returned. If there is an error, NULL is returned.
-
- Note This function is a rewrite of the FExpand procedure
- in the Turbo Pascal RTL, with modifications for MSC
- compatibility.
-
- *---------------------------------------------------------------------*/
- char * _CType _FARFUNC _fullpath(char *buffer,
- const char *pathname,
- size_t maxlen
- )
- {
- char *tempbuf;
- char *dst, *src;
- int c, len, driveletter;
- unsigned drive;
-
- /* Allocate a temporary buffer to hold the fully qualified path.
- */
- if ((tempbuf = malloc(_MAX_PATH*2+1)) == NULL)
- return (NULL);
-
- /* Check for a drive name. If one is not provided,
- * get the current drive. Point src at the first
- * character in pathname after the drive name, if any.
- */
- src = (char *)pathname;
- if (isalpha(src[0]) && src[1] == ':')
- {
- drive = toupper(driveletter = src[0]) - 'A' + 1;
- src += 2;
- }
- else
- {
- _dos_getdrive(&drive); /* get current drive */
- driveletter = drive + 'A' - 1;
- }
-
- /* If supplied path is relative, append it to the drivename
- * and its current directory. Otherwise append it to the
- * drivename only.
- */
- if (!isSlash(src[0])) /* path is relative? */
- {
- /* Get drivename and its current directory.
- */
- if (_getdcwd(drive,tempbuf,_MAX_PATH*2+1) == NULL)
- {
- free(tempbuf);
- return (NULL);
- }
- dst = &tempbuf[strlen(tempbuf)];
- if (!isSlash(*(dst-1))) /* if directory doesn't end in slash */
- *dst++ = '\\'; /* append one */
- }
- else
- {
- /* Path is absolute. Store the drivename only.
- */
- dst = tempbuf;
- *dst++ = driveletter;
- *dst++ = ':';
- }
- strcpy(dst,src); /* concatenate supplied path */
-
- /* Scan the path, squeezing out "..\" and ".\", and
- * squeezing out the previous directory when "..\" is found.
- */
- src = dst = tempbuf;
- for (;;)
- {
- /* If this the end of the path, or end of a directory,
- * we must check for "." or ".."
- */
- if ((c = *src++) == '\0' || isSlash(c))
- {
- /* If last directory copied was "\.", back up over it.
- */
- if (*(dst-1) == '.' && isSlash(*(dst-2)))
- dst -= 2;
-
- /* If last directory copied was "\..", back up over it
- * AND the previous directory.
- */
- else if (*(dst-1) == '.' && *(dst-2) == '.' && isSlash(*(dst-3)))
- {
- dst -= 3; /* back up over "\.." */
- if (*(dst-1) == ':') /* can't back up over drivename */
- {
- free(tempbuf);
- return(NULL);
- }
- while (!isSlash(*--dst))
- ; /* back up to start of prev. dir. */
- }
-
- if (c == '\0') /* end of path? */
- {
- if (isSlash(*(dst-1))) /* if last char is slash */
- dst--; /* back up over it */
- if (*(dst-1) == ':') /* if path is just a drivename */
- *dst++ = '\\'; /* append a slash */
- *dst = '\0'; /* append null terminator */
- break;
- }
- else
- *dst++ = c; /* copy the slash */
- }
- else
- *dst++ = c; /* copy the character */
- }
-
- /* Copy the temp buffer to the user's buffer, if present.
- * Otherwise shrink the temp buffer and return a pointer to it.
- */
- len = strlen(tempbuf) + 1; /* length of path and null */
- if (buffer != NULL)
- {
- if (len > maxlen) /* user buffer too small? */
- {
- free(tempbuf);
- return (NULL);
- }
- else
- {
- strcpy(buffer,tempbuf);
- free(tempbuf);
- return (buffer);
- }
- }
- else
- return (realloc(tempbuf,len)); /* shrink the buffer */
- }
-