BBN-Vax-TCP/src/libbbn/dotpath.c
/*
* char *dotpath(relpath, low, top)
* Take any legal pathname, relpath, and put the equivalent most
* reduced pathname that can be obtained without accessing any
* file systems in the area pointed to by low, but not exceeding top.
* A pointer to the null of the resultant string is returned.
*
* The resultant string starts with one of "/", ".", or "...".
* If it starts with "/", all occurences of "." and ".." have been
* removed (there was no "...") and the pathname is absolute and
* condensed as much as possible. If it starts with "." or "...",
* all other occurences of "." or "..." have been removed, as have
* all occurences of ".." which would not involve backing past the
* initial "." or "...". In any case, all multiple adjacent slashes
* have been reduced to one, and any trailing slash has been removed.
*
* There are no possible errors except lack of space to put the string.
*/
char *dotpath (relpath, low, top)
char *relpath;
char *low;
char *top;
{
register char *cp,
*path;
char *ep,
*slash,
*root,
*dot,
*dotdot,
*dotdotdot;
char *start;
int slength (), smatch (), stokeq ();
char *sskip (), *sfind (), *scopy (), *safter ();
char *sbskip (), *sbfind (), *sbcopy ();
root = "/";
slash = "/";
dot = ".";
dotdot = "..";
dotdotdot = "...";
cp = relpath;
path = low;
if (smatch (cp, root) == slength (root))
{
start = path;
path = scopy (root, path, top);
cp = sskip (safter (cp, root), slash);
}
else
{
path = scopy (dot, path, top);
path = scopy (slash, path, top);
start = path;
}
ep = path;
while (*cp)
{
if (stokeq (cp, slash, dot))
{ /* just ignore dot */
cp = sskip (sfind (cp, slash), slash);
}
else
if (stokeq (cp, slash, dotdot)
&& (path > start) && !stokeq (ep, slash, dotdot))
{ /* back up */
cp = sskip (sfind (cp, slash), slash);
path = ep;
if (sbskip (ep, low, slash) > start)
{
ep = sbfind (sbskip (ep, low, slash), low, slash);
}
}
else
if (stokeq (cp, slash, dotdotdot))
{ /* start over */
cp = sskip (sfind (cp, slash), slash);
path = scopy (dotdotdot, low, top);
start = ep = path = scopy (slash, path, top);
}
else
{
ep = path;
path = scopy (cp, path, &path[sfind (cp, slash) - cp]);
if (!seq (low, root))
path = scopy (slash, path, top);
cp = sskip (sfind (cp, slash), slash);
}
*path = 0;
}
if (!seq (low, root))
{ /* wipe out trailing slash */
path = sbskip (path, low, slash);
*path = 0;
}
return (path);
}