Added a normalize_path() function, that does a certain normalization of paths.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6546 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
bf3a9e7597
commit
74c89bd7f8
@ -49,3 +49,4 @@ void path_build( PATHNAME *f, char *file, int binding );
|
|||||||
void path_parse( const char *file, PATHNAME *f );
|
void path_parse( const char *file, PATHNAME *f );
|
||||||
void path_parent( PATHNAME *f );
|
void path_parent( PATHNAME *f );
|
||||||
|
|
||||||
|
char *normalize_path(const char *path, char *buffer, size_t bufferSize);
|
||||||
|
@ -232,4 +232,96 @@ path_parent( PATHNAME *f )
|
|||||||
f->f_member.len = 0;
|
f->f_member.len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* normalize_path() - normalize a path
|
||||||
|
*
|
||||||
|
* It doesn't really generate a unique representation of a path to an entry,
|
||||||
|
* but at least reduces the number of categories that represent the same
|
||||||
|
* entry. On error, or if the supplied buffer is too small, NULL is returned.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *
|
||||||
|
normalize_path(const char *path, char *buffer, size_t bufferSize)
|
||||||
|
{
|
||||||
|
// init cwd
|
||||||
|
static char _cwd[PATH_MAX];
|
||||||
|
static char *cwd = 0;
|
||||||
|
static size_t cwdLen = 0;
|
||||||
|
int pathLen = (path ? strlen(path) : 0);
|
||||||
|
int resultLen = 0;
|
||||||
|
int resolveDotDot = !0;
|
||||||
|
// init cwd
|
||||||
|
if (!cwd) {
|
||||||
|
cwd = getcwd(_cwd, PATH_MAX);
|
||||||
|
if (cwd)
|
||||||
|
cwdLen = strlen(cwd);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// check length
|
||||||
|
if (cwdLen + pathLen + 2 > bufferSize)
|
||||||
|
return 0;
|
||||||
|
// construct result
|
||||||
|
if (pathLen > 0 && path[0] == PATH_DELIM) {
|
||||||
|
// absolute path: ignore cwd
|
||||||
|
buffer[0] = PATH_DELIM;
|
||||||
|
buffer[1] = '\0';
|
||||||
|
resultLen = 1;
|
||||||
|
path++;
|
||||||
|
pathLen--;
|
||||||
|
} else {
|
||||||
|
// relative path: copy cwd into result
|
||||||
|
memcpy(buffer, cwd, cwdLen + 1);
|
||||||
|
resultLen = cwdLen;
|
||||||
|
}
|
||||||
|
// append path componentwise to the result, skipping "." and empty
|
||||||
|
// components, and chopping off a component per ".."
|
||||||
|
while (pathLen > 0) {
|
||||||
|
// find component
|
||||||
|
char *separator = strchr(path, PATH_DELIM);
|
||||||
|
const char *component = path;
|
||||||
|
int componentLen = 0;
|
||||||
|
if (separator) {
|
||||||
|
componentLen = separator - path;
|
||||||
|
pathLen -= componentLen + 1;
|
||||||
|
path = separator + 1;
|
||||||
|
} else {
|
||||||
|
componentLen = pathLen;
|
||||||
|
path += componentLen;
|
||||||
|
pathLen = 0;
|
||||||
|
}
|
||||||
|
// handle found component
|
||||||
|
if (componentLen > 0) {
|
||||||
|
if (componentLen == 1 && component[0] == '.') {
|
||||||
|
// component is ".": skip
|
||||||
|
} else if (resolveDotDot && componentLen == 2 && component[0] == '.'
|
||||||
|
&& component[1] == '.') {
|
||||||
|
// component is "..": eat the last component of the result
|
||||||
|
char *lastSeparator = strrchr(buffer, PATH_DELIM);
|
||||||
|
if (lastSeparator) {
|
||||||
|
resultLen = lastSeparator - buffer;
|
||||||
|
if (resultLen == 0) {
|
||||||
|
// always leave at least the root
|
||||||
|
buffer[0] = PATH_DELIM;
|
||||||
|
resultLen = 1;
|
||||||
|
}
|
||||||
|
buffer[resultLen] = '\0';
|
||||||
|
} // else: not good
|
||||||
|
} else {
|
||||||
|
// normal component: append
|
||||||
|
if (resultLen < 1 || buffer[resultLen - 1] != PATH_DELIM)
|
||||||
|
buffer[resultLen++] = PATH_DELIM;
|
||||||
|
memcpy(buffer + resultLen, component, componentLen);
|
||||||
|
resultLen += componentLen;
|
||||||
|
buffer[resultLen] = '\0';
|
||||||
|
// After we found the first real path component, we don't
|
||||||
|
// resolve ".." anymore, as it could be a (sym)link, which
|
||||||
|
// could break the algorithm.
|
||||||
|
resolveDotDot = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
# endif /* unix, NT, OS/2, AmigaOS */
|
# endif /* unix, NT, OS/2, AmigaOS */
|
||||||
|
Loading…
Reference in New Issue
Block a user