a
This commit is contained in:
52
libc/cleanname.c
Normal file
52
libc/cleanname.c
Normal file
@ -0,0 +1,52 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
|
||||
/*
|
||||
* In place, rewrite name to compress multiple /, eliminate ., and process ..
|
||||
*/
|
||||
#define SEP(x) ((x)=='/' || (x) == 0)
|
||||
char*
|
||||
cleanname(char *name)
|
||||
{
|
||||
char *p, *q, *dotdot;
|
||||
int rooted;
|
||||
|
||||
rooted = name[0] == '/';
|
||||
|
||||
/*
|
||||
* invariants:
|
||||
* p points at beginning of path element we're considering.
|
||||
* q points just past the last path element we wrote (no slash).
|
||||
* dotdot points just past the point where .. cannot backtrack
|
||||
* any further (no slash).
|
||||
*/
|
||||
p = q = dotdot = name+rooted;
|
||||
while(*p) {
|
||||
if(p[0] == '/') /* null element */
|
||||
p++;
|
||||
else if(p[0] == '.' && SEP(p[1]))
|
||||
p += 1; /* don't count the separator in case it is nul */
|
||||
else if(p[0] == '.' && p[1] == '.' && SEP(p[2])) {
|
||||
p += 2;
|
||||
if(q > dotdot) { /* can backtrack */
|
||||
while(--q > dotdot && *q != '/')
|
||||
;
|
||||
} else if(!rooted) { /* /.. is / but ./../ is .. */
|
||||
if(q != name)
|
||||
*q++ = '/';
|
||||
*q++ = '.';
|
||||
*q++ = '.';
|
||||
dotdot = q;
|
||||
}
|
||||
} else { /* real path element */
|
||||
if(q != name+rooted)
|
||||
*q++ = '/';
|
||||
while((*q = *p) != '/' && *q != 0)
|
||||
p++, q++;
|
||||
}
|
||||
}
|
||||
if(q == name) /* empty string is really ``.'' */
|
||||
*q++ = '.';
|
||||
*q = '\0';
|
||||
return name;
|
||||
}
|
Reference in New Issue
Block a user