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