cleanname.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       cleanname.c (1536B)
       ---
            1 #include "u.h"
            2 #include "lib.h"
            3 
            4 /*
            5  * In place, rewrite name to compress multiple /, eliminate ., and process ..
            6  */
            7 #define SEP(x)        ((x)=='/' || (x) == 0)
            8 char*
            9 cleanname(char *name)
           10 {
           11         char *p, *q, *dotdot;
           12         int rooted, erasedprefix;
           13 
           14         rooted = name[0] == '/';
           15         erasedprefix = 0;
           16 
           17         /*
           18          * invariants:
           19          *        p points at beginning of path element we're considering.
           20          *        q points just past the last path element we wrote (no slash).
           21          *        dotdot points just past the point where .. cannot backtrack
           22          *                any further (no slash).
           23          */
           24         p = q = dotdot = name+rooted;
           25         while(*p) {
           26                 if(p[0] == '/')        /* null element */
           27                         p++;
           28                 else if(p[0] == '.' && SEP(p[1])) {
           29                         if(p == name)
           30                                 erasedprefix = 1;
           31                         p += 1;        /* don't count the separator in case it is nul */
           32                 } else if(p[0] == '.' && p[1] == '.' && SEP(p[2])) {
           33                         p += 2;
           34                         if(q > dotdot) {        /* can backtrack */
           35                                 while(--q > dotdot && *q != '/')
           36                                         ;
           37                         } else if(!rooted) {        /* /.. is / but ./../ is .. */
           38                                 if(q != name)
           39                                         *q++ = '/';
           40                                 *q++ = '.';
           41                                 *q++ = '.';
           42                                 dotdot = q;
           43                         }
           44                         if(q == name)
           45                                 erasedprefix = 1;        /* erased entire path via dotdot */
           46                 } else {        /* real path element */
           47                         if(q != name+rooted)
           48                                 *q++ = '/';
           49                         while((*q = *p) != '/' && *q != 0)
           50                                 p++, q++;
           51                 }
           52         }
           53         if(q == name)        /* empty string is really ``.'' */
           54                 *q++ = '.';
           55         *q = '\0';
           56         if(erasedprefix && name[0] == '#'){        
           57                 /* this was not a #x device path originally - make it not one now */
           58                 memmove(name+2, name, strlen(name)+1);
           59                 name[0] = '.';
           60                 name[1] = '/';
           61         }
           62         return name;
           63 }