Changeset 21631 for trunk/src


Ignore:
Timestamp:
Apr 28, 2011, 10:59:02 PM (14 years ago)
Author:
dmik
Message:

minivcrt: Fixed _fullpath()/_wfullpath() which was broken in many regards (i.e. it would eat path components starting with "." and "..").

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/msvcrt/dir.c

    r21550 r21631  
    572572}
    573573
    574 /* INTERNAL: Helper for _fullpath. Modified PD code from 'snippets'. */
    575 static void msvcrt_fln_fix(char *path)
    576 {
    577   int dir_flag = 0, root_flag = 0;
    578   char *r, *p, *q, *s;
    579 
    580   /* Skip drive */
    581   if (NULL == (r = strrchr(path, ':')))
    582     r = path;
    583   else
    584     ++r;
    585 
    586   /* Ignore leading slashes */
    587   while ('\\' == *r)
    588     if ('\\' == r[1])
    589       strcpy(r, &r[1]);
    590     else
    591     {
    592       root_flag = 1;
    593       ++r;
    594     }
    595 
    596   p = r; /* Change "\\" to "\" */
    597   while (NULL != (p = strchr(p, '\\')))
    598     if ('\\' ==  p[1])
    599       strcpy(p, &p[1]);
    600     else
    601       ++p;
    602 
    603   while ('.' == *r) /* Scrunch leading ".\" */
    604   {
    605     if ('.' == r[1])
    606     {
    607       /* Ignore leading ".." */
    608       for (p = (r += 2); *p && (*p != '\\'); ++p)
    609         ;
    610     }
    611     else
    612     {
    613       for (p = r + 1 ;*p && (*p != '\\'); ++p)
    614         ;
    615     }
    616     strcpy(r, p + ((*p) ? 1 : 0));
    617   }
    618 
    619   while ('\\' == path[strlen(path)-1])   /* Strip last '\\' */
    620   {
    621     dir_flag = 1;
    622     path[strlen(path)-1] = '\0';
    623   }
    624 
    625   s = r;
    626 
    627   /* Look for "\." in path */
    628 
    629   while (NULL != (p = strstr(s, "\\.")))
    630   {
    631     if ('.' == p[2])
    632     {
    633       /* Execute this section if ".." found */
    634       q = p - 1;
    635       while (q > r)           /* Backup one level           */
    636       {
    637         if (*q == '\\')
    638           break;
    639         --q;
    640       }
    641       if (q > r)
    642       {
    643         strcpy(q, p + 3);
    644         s = q;
    645       }
    646       else if ('.' != *q)
    647       {
    648         strcpy(q + ((*q == '\\') ? 1 : 0),
    649                p + 3 + ((*(p + 3)) ? 1 : 0));
    650         s = q;
    651       }
    652       else  s = ++p;
    653     }
    654     else
    655     {
    656       /* Execute this section if "." found */
    657       q = p + 2;
    658       for ( ;*q && (*q != '\\'); ++q)
    659         ;
    660       strcpy (p, q);
    661     }
    662   }
    663 
    664   if (root_flag)  /* Embedded ".." could have bubbled up to root  */
    665   {
    666     for (p = r; *p && ('.' == *p || '\\' == *p); ++p)
    667       ;
    668     if (r != p)
    669       strcpy(r, p);
    670   }
    671 
    672   if (dir_flag)
    673     strcat(path, "\\");
     574static char *msvcrt_clean_path(char *path)
     575{
     576    char *cur, *sep, *next;
     577
     578    /* convert "/" => "\" */
     579    cur = path;
     580    while (*cur)
     581    {
     582        if (*cur == '/')
     583            *cur = '\\';
     584        ++cur;
     585    }
     586
     587    cur = path;
     588    while (*cur)
     589    {
     590        sep = strchr(cur, '\\');
     591        if (!sep)
     592            sep = cur + strlen(cur);
     593
     594        next = sep;
     595        while (*next == '\\')
     596            ++next;
     597
     598        if (sep - cur == 1 && *cur == '.')
     599        {
     600            /* eat "." */
     601            strcpy(cur, next);
     602        }
     603        else if (sep - cur == 2 && cur[0] == '.' && cur[1] == '.')
     604        {
     605            /* go one level up if there is any */
     606            if (cur - path > 1 && cur[-2] != ':')
     607            {
     608                cur -= 2;
     609                while (cur > path && *cur != '\\')
     610                    --cur;
     611                if (*cur == '\\')
     612                    ++cur;
     613            }
     614            strcpy(cur, next);
     615        }
     616        else if (next - sep > 1)
     617        {
     618            /* eat multiple "\\" */
     619            cur = sep + 1;
     620            strcpy(cur, next);
     621        }
     622        else
     623        {
     624            cur = next;
     625        }
     626    }
     627
     628    /* strip trailing '\' unless it indicates the root path */
     629    if (cur - path > 1 && cur[-1] == '\\' && cur[-2] != ':')
     630        *--cur = '\0';
     631
     632    return path;
    674633}
    675634
     
    686645
    687646  if (!relPath || !*relPath)
    688     return MSVCRT(_getcwd)(absPath, size);
     647    return msvcrt_clean_path(MSVCRT(_getcwd)(absPath, size));
    689648
    690649  if (size < 4)
     
    711670  else
    712671  {
     672    if (!drive[0])
     673    {
     674      drive[0] = _getdrive();
     675      drive[1] = ':';
     676      drive[2] = '\0';
     677    }
    713678    strcpy(res,drive);
    714679    strcat(res,dir);
     
    718683  strcat(res, file);
    719684  strcat(res, ext);
    720   msvcrt_fln_fix(res);
     685  msvcrt_clean_path(res);
    721686
    722687  len = strlen(res);
Note: See TracChangeset for help on using the changeset viewer.