1*7ded4a52SCharles Forsyth #include "lib9.h" 237da2899SCharles.Forsyth 337da2899SCharles.Forsyth /* 437da2899SCharles.Forsyth * In place, rewrite name to compress multiple /, eliminate ., and process .. 537da2899SCharles.Forsyth */ 637da2899SCharles.Forsyth #define SEP(x) ((x)=='/' || (x) == 0) 737da2899SCharles.Forsyth char* cleanname(char * name)837da2899SCharles.Forsythcleanname(char *name) 937da2899SCharles.Forsyth { 1037da2899SCharles.Forsyth char *p, *q, *dotdot; 11*7ded4a52SCharles Forsyth int rooted, erasedprefix; 1237da2899SCharles.Forsyth 1337da2899SCharles.Forsyth rooted = name[0] == '/'; 14*7ded4a52SCharles Forsyth erasedprefix = 0; 1537da2899SCharles.Forsyth 1637da2899SCharles.Forsyth /* 1737da2899SCharles.Forsyth * invariants: 1837da2899SCharles.Forsyth * p points at beginning of path element we're considering. 1937da2899SCharles.Forsyth * q points just past the last path element we wrote (no slash). 2037da2899SCharles.Forsyth * dotdot points just past the point where .. cannot backtrack 2137da2899SCharles.Forsyth * any further (no slash). 2237da2899SCharles.Forsyth */ 2337da2899SCharles.Forsyth p = q = dotdot = name+rooted; 2437da2899SCharles.Forsyth while(*p) { 2537da2899SCharles.Forsyth if(p[0] == '/') /* null element */ 2637da2899SCharles.Forsyth p++; 27*7ded4a52SCharles Forsyth else if(p[0] == '.' && SEP(p[1])) { 28*7ded4a52SCharles Forsyth if(p == name) 29*7ded4a52SCharles Forsyth erasedprefix = 1; 3037da2899SCharles.Forsyth p += 1; /* don't count the separator in case it is nul */ 31*7ded4a52SCharles Forsyth } else if(p[0] == '.' && p[1] == '.' && SEP(p[2])) { 3237da2899SCharles.Forsyth p += 2; 3337da2899SCharles.Forsyth if(q > dotdot) { /* can backtrack */ 3437da2899SCharles.Forsyth while(--q > dotdot && *q != '/') 3537da2899SCharles.Forsyth ; 3637da2899SCharles.Forsyth } else if(!rooted) { /* /.. is / but ./../ is .. */ 3737da2899SCharles.Forsyth if(q != name) 3837da2899SCharles.Forsyth *q++ = '/'; 3937da2899SCharles.Forsyth *q++ = '.'; 4037da2899SCharles.Forsyth *q++ = '.'; 4137da2899SCharles.Forsyth dotdot = q; 4237da2899SCharles.Forsyth } 43*7ded4a52SCharles Forsyth if(q == name) 44*7ded4a52SCharles Forsyth erasedprefix = 1; /* erased entire path via dotdot */ 4537da2899SCharles.Forsyth } else { /* real path element */ 4637da2899SCharles.Forsyth if(q != name+rooted) 4737da2899SCharles.Forsyth *q++ = '/'; 4837da2899SCharles.Forsyth while((*q = *p) != '/' && *q != 0) 4937da2899SCharles.Forsyth p++, q++; 5037da2899SCharles.Forsyth } 5137da2899SCharles.Forsyth } 5237da2899SCharles.Forsyth if(q == name) /* empty string is really ``.'' */ 5337da2899SCharles.Forsyth *q++ = '.'; 5437da2899SCharles.Forsyth *q = '\0'; 55*7ded4a52SCharles Forsyth if(erasedprefix && name[0] == '#'){ 56*7ded4a52SCharles Forsyth /* this was not a #x device path originally - make it not one now */ 57*7ded4a52SCharles Forsyth memmove(name+2, name, strlen(name)+1); 58*7ded4a52SCharles Forsyth name[0] = '.'; 59*7ded4a52SCharles Forsyth name[1] = '/'; 60*7ded4a52SCharles Forsyth } 6137da2899SCharles.Forsyth return name; 6237da2899SCharles.Forsyth } 63