vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | 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 }