char *dfnfullpath(const char * const fnam) { char *fullpath; char *paths; char *q; /* intermediate pointers */ char *nxtDelim; int cnt; #ifdef OS_WIN32 #ifdef SUPPORT_UNC_PATH DBG_ENTER("dfnufullpath2", Suppl_dfn) #else DBG_ENTER("dfnfullpath2", Suppl_dfn) #endif #else #ifdef SUPPORT_UNC_PATH DBG_ENTER("dfnufullpath", Suppl_dfn) #else DBG_ENTER("dfnfullpath", Suppl_dfn) #endif #endif assert(fnam); DBG_ARGUMENTS( ("fnam=\"%s\"", fnam) ) chkHeap if((fullpath = dfnexpand(fnam, 0)) == 0) DBG_RETURN_S( 0) assert(*fullpath); #ifdef SUPPORT_UNC_PATH if(isUNCpath(fullpath)) paths = UNCpath(fullpath); else #endif { assert(*fullpath && fullpath[1] == ':'); paths = &fullpath[2]; } chkHeap assert(*paths == '\\'); q = paths; while(*q == '\\' && *++q) { /* Check for special directories */ if((nxtDelim = strchr(q, '\\')) == 0) nxtDelim = strchr(q, '\0'); if((cnt = strspn(q, ".")) == nxtDelim - q #ifndef FEATURE_LONG_FILENAMES && cnt < 3 /* DOS limits to "." and ".." */ #endif ) { /* all dots --> special directory */ /* Relocate "q" (cnt-1) path components to the left */ while(--q > paths && --cnt) { /* search next '\' to the left */ while(*--q != '\\'); ++q; } if(*nxtDelim) { /* some components left, move them up */ /* Note: *nxtDelim == *q == '\\', but by copying over this single character one needs not implement a special handling if nxtDelim[1] == '\0' */ memmove(q, nxtDelim, strlen(nxtDelim) + 1); } else { /* this was the last component, but because this was a special directory, the information must be preserved that it is a directory --> append trailing backslash */ q[1] = '\0'; } } else { q = nxtDelim; } } chkHeap DBG_RETURN_S( StrTrim(fullpath)) }
char *dfnexpand(const char * const fnam, char * const path) { char *h, *p; /* intermediate pointers */ char *dr, *pa, *na, *ex; /* filename components */ char pathDr, *pathPa; /* drive & path of 'path' */ char *dynPath; #ifdef SUPPORT_UNC_PATH DBG_ENTER("dfnuexpand", Suppl_dfn) #else DBG_ENTER("dfnexpand", Suppl_dfn) #endif assert(fnam); DBG_ARGUMENTS( ("fnam=\"%s\", path=\"%s\"", fnam, path) ) chkHeap if((h = dfnsqueeze(fnam)) == 0) DBG_RETURN_S( 0) #ifdef SUPPORT_UNC_PATH if(isUNCpath(h)) { /* UNC paths are always fully-qualified */ /* check if the trailing '\\' is present to mark the root direc */ DBG_RETURN_BS((*UNCpath(h) != '\\')? StrAppChr(h, '\\') : h) } #endif chkHeap if(!*h || h[1] != ':' || h[2] != '\\') { /* the spec is not fully-qualified or completely empty */ pathDr = 0; dynPath = 0; if((pathPa = path) != 0 && *pathPa) { if(pathPa[1] == ':') { /* path[] has drive spec */ pathDr = *path; if(!*(pathPa += 2)) { pathPa = 0; goto noPath; } } if(dfndelim(*pathPa) && !pathPa[1]) ++pathPa; /* Trans "/" || "\\" --> "" */ noPath:; } chkHeap if(dfnsplit(h, &dr, &pa, &na, &ex)) { StrFree(h); if(dr) { /* drive specified */ if(pathDr && toFUpper(pathDr) != *dr) /* The specified path is for a different drive */ pathPa = 0; } else { /* drive spec missing */ if((dr = StrChar(pathDr? pathDr: 'A' + getdisk())) == 0) goto errRet; } if(!pa || *pa != '\\' && *pa != NUL) { /* no path or a relative one */ if(!pathPa) { /* path has no path spec in it */ if((dynPath = dfnpath(*dr)) == 0) goto errRet; pathPa = dynPath + 2; } if((p = dfnmerge(0, 0, pathPa, pa, 0)) == 0) goto errRet; StrRepl(pa, p); } h = dfnmerge(0, dr, pa, na, ex); } else StrFree(h); errRet: chkHeap free(dr); free(pa); free(na); free(ex); free(dynPath); }