/************************************************************************* * RootPath -- Convert a pathname argument to root based cannonical * * form. * * Author: Don A. Williams * * CompuServ - * * Genie - DON-WILL * * * * RootPath determines the current directory, appends the path argument * * (which may affect which disk the current directory is relative to), * * and qualifies "." and ".." references. The result is a complete, * * simple, path name with drive specifier. * * * * If the relative path the user specifies does not include a drive * * spec., the default drive will be used as the base. (The default drive * * will never be changed.) * * * * entry: RelativePath -- pointer to the pathname to be expanded. * * FullPath -- must point to a working buffer, see warning. * * * * exit: FullPath -- the full path which results. * * * * return: A pointer to FullPath if OK, NULL if an error occurs. * * * calls: getcurdir getdisk * * * * warning: FullPath must point to a working buffer large enough to * * hold the longest possible relative path argument plus * * the longest possible current directory path. * * * * RootPath was modeled after the public domain file "rootpath.c" with * * fairly extensive "enhancement". The major enhancement is provision * * for relative paths such as "..\..\here" which MS-DOS does NOT * * support. I found that such a construct would be very handy in * * several of my uses of UFIND so I added it. Provision has also been * * made to handle either of the two element name separator characters; * * the '\' of MS-DOS or the '/' of Unix. The MS-DOS facilities actually * * recognize either separator at the programmatic level but too many * * MS-DOS programs do NOT. * * * ************************************************************************/ #include #include #include int GetCurrentDirectory(int Disk, char *CurDir); char * RootPath (char *CurDir, char *RelPath, char *FullPath) { char *p, *p1, *p2; if (RelPath[0] == '\0') { FullPath[0] = '\0'; return (NULL); } if (RelPath[1] == ':') { /* Path contains drive */ FullPath[0] = RelPath[0]; FullPath[1] = RelPath[1]; memmove(RelPath, RelPath + 2, strlen(RelPath) + 1); } else { FullPath[0] = CurDir[0]; FullPath[1] = CurDir[1]; } FullPath[2] = '\0'; if (strlen(RelPath) == 2 && *(RelPath + 1) == ':') strcat(RelPath, "\\"); if ((p = strchr("\\/", *RelPath)) != NULL) strcpy(FullPath + 2, RelPath); else { FullPath[2] = '\\'; if (FullPath[0] != CurDir[0]) { if (GetCurrentDirectory((int) (toupper(*FullPath) - '@'), &FullPath[3])) return (NULL); } else { strcpy(FullPath, CurDir); FullPath[strlen(FullPath) - 1] = '\0'; } p = RelPath; while (1) { p1 = strchr(p, '\\'); if (!strncmp(p, "..", 2)) { if ((p2 = strrchr(FullPath, '\\')) != NULL) *p2 = '\0'; p = p1 + 1; } else if (!strncmp(p, ".", 1)) { p = p1 + 1; break; }; if (p1 == NULL) break; } if ((strlen(FullPath) > 3) || (strlen(FullPath) == 2)) strcat(FullPath, "\\"); strcat(FullPath, p); } while ((p = strchr(FullPath, '/')) != NULL) *p++ = '\\'; if ((strlen(FullPath) == 3) && (FullPath[2] == '\\')) FullPath[2] = '\0'; return (strlwr(FullPath)); }