17dd7cddfSDavid du Colombier #include <u.h> 27dd7cddfSDavid du Colombier #include <libc.h> 37dd7cddfSDavid du Colombier 47dd7cddfSDavid du Colombier /* 57dd7cddfSDavid du Colombier * In place, rewrite name to compress multiple /, eliminate ., and process .. 67dd7cddfSDavid du Colombier */ 77dd7cddfSDavid du Colombier #define SEP(x) ((x)=='/' || (x) == 0) 87dd7cddfSDavid du Colombier char* cleanname(char * name)97dd7cddfSDavid du Colombiercleanname(char *name) 107dd7cddfSDavid du Colombier { 11*853458f3SDavid du Colombier char *s; /* source of copy */ 12*853458f3SDavid du Colombier char *d; /* destination of copy */ 13*853458f3SDavid du Colombier char *d0; /* start of path afer the root name */ 14*853458f3SDavid du Colombier Rune r; 15*853458f3SDavid du Colombier int rooted; 167dd7cddfSDavid du Colombier 17*853458f3SDavid du Colombier if(name[0] == 0) 18*853458f3SDavid du Colombier return strcpy(name, "."); 19*853458f3SDavid du Colombier rooted = 0; 20*853458f3SDavid du Colombier d0 = name; 21*853458f3SDavid du Colombier if(d0[0] == '#'){ 22*853458f3SDavid du Colombier if(d0[1] == 0) 23*853458f3SDavid du Colombier return d0; 24*853458f3SDavid du Colombier d0 += 1 + chartorune(&r, d0+1); /* ignore slash: #/ */ 25*853458f3SDavid du Colombier while(!SEP(*d0)) 26*853458f3SDavid du Colombier d0 += chartorune(&r, d0); 27*853458f3SDavid du Colombier if(d0 == 0) 28*853458f3SDavid du Colombier return name; 29*853458f3SDavid du Colombier d0++; /* keep / after #<name> */ 30*853458f3SDavid du Colombier rooted = 1; 31*853458f3SDavid du Colombier }else if(d0[0] == '/'){ 32*853458f3SDavid du Colombier rooted = 1; 33*853458f3SDavid du Colombier d0++; 34*853458f3SDavid du Colombier } 357dd7cddfSDavid du Colombier 36*853458f3SDavid du Colombier s = d0; 37*853458f3SDavid du Colombier if(rooted){ 38*853458f3SDavid du Colombier /* skip extra '/' at root name */ 39*853458f3SDavid du Colombier for(; *s == '/'; s++) 407dd7cddfSDavid du Colombier ; 417dd7cddfSDavid du Colombier } 42*853458f3SDavid du Colombier /* remove dup slashes */ 43*853458f3SDavid du Colombier for(d = d0; *s != 0; s++){ 44*853458f3SDavid du Colombier *d++ = *s; 45*853458f3SDavid du Colombier if(*s == '/') 46*853458f3SDavid du Colombier while(s[1] == '/') 47*853458f3SDavid du Colombier s++; 48*853458f3SDavid du Colombier } 49*853458f3SDavid du Colombier *d = 0; 50*853458f3SDavid du Colombier 51*853458f3SDavid du Colombier d = d0; 52*853458f3SDavid du Colombier s = d0; 53*853458f3SDavid du Colombier while(*s != 0){ 54*853458f3SDavid du Colombier if(s[0] == '.' && SEP(s[1])){ 55*853458f3SDavid du Colombier if(s[1] == 0) 56*853458f3SDavid du Colombier break; 57*853458f3SDavid du Colombier s+= 2; 58*853458f3SDavid du Colombier continue; 59*853458f3SDavid du Colombier } 60*853458f3SDavid du Colombier if(s[0] == '.' && s[1] == '.' && SEP(s[2])){ 61*853458f3SDavid du Colombier if(d == d0){ 62*853458f3SDavid du Colombier if(rooted){ 63*853458f3SDavid du Colombier /* /../x -> /x */ 64*853458f3SDavid du Colombier if(s[2] == 0) 65*853458f3SDavid du Colombier break; 66*853458f3SDavid du Colombier s += 3; 67*853458f3SDavid du Colombier continue; 68*853458f3SDavid du Colombier }else{ 69*853458f3SDavid du Colombier /* ../x -> ../x; and never collect ../ */ 70*853458f3SDavid du Colombier d0 += 3; 717dd7cddfSDavid du Colombier } 727dd7cddfSDavid du Colombier } 73*853458f3SDavid du Colombier if(d > d0){ 74*853458f3SDavid du Colombier /* a/../x -> x */ 75*853458f3SDavid du Colombier assert(d-2 >= d0 && d[-1] == '/'); 76*853458f3SDavid du Colombier for(d -= 2; d > d0 && d[-1] != '/'; d--) 77*853458f3SDavid du Colombier ; 78*853458f3SDavid du Colombier if(s[2] == 0) 79*853458f3SDavid du Colombier break; 80*853458f3SDavid du Colombier s += 3; 81*853458f3SDavid du Colombier continue; 82c35931e2SDavid du Colombier } 83*853458f3SDavid du Colombier } 84*853458f3SDavid du Colombier while(!SEP(*s)) 85*853458f3SDavid du Colombier *d++ = *s++; 86*853458f3SDavid du Colombier if(*s == 0) 87*853458f3SDavid du Colombier break; 88*853458f3SDavid du Colombier 89*853458f3SDavid du Colombier *d++ = *s++; 90*853458f3SDavid du Colombier } 91*853458f3SDavid du Colombier *d = 0; 92*853458f3SDavid du Colombier if(d-1 > name && d[-1] == '/') /* thanks to #/ */ 93*853458f3SDavid du Colombier *--d = 0; 94*853458f3SDavid du Colombier if(name[0] == 0) 95*853458f3SDavid du Colombier strcpy(name, "."); 967dd7cddfSDavid du Colombier return name; 977dd7cddfSDavid du Colombier } 98