/* pathcode/fget_relativepath.c. Generated from relativepath.c.in by configure. */
/*
** Copyright 1998-2002 University of Illinois Board of Trustees
** Copyright 1998-2002 Mark D. Roth
** All rights reserved.
**
** fget_relativepath.c - find relative path between two absolute paths
**
** Mark D. Roth <roth@uiuc.edu>
** Campus Information Technologies and Educational Services
** University of Illinois at Urbana-Champaign
*/
#include <fget_pathcode.h>
#include <stdio.h>
#include <sys/param.h>
#include <errno.h>
#ifdef STDC_HEADERS
# include <string.h>
#endif
/*
** fget_relativepath() - return a relative path from start_dir to finish_dir
** returns:
** 0 success
** -1 failure (and sets errno)
*/
int
fget_relativepath(char *start_dir, char *finish_dir,
char *buf, size_t bufsize)
{
char buf1[MAXPATHLEN], buf2[MAXPATHLEN];
char *nextp1 = buf1, *nextp2 = buf2, *tok1, *tok2;
#ifdef DEBUG
printf("==> fget_relativepath(\"%s\", \"%s\", 0x%lx, %d)\n",
start_dir, finish_dir, buf, bufsize);
#endif
buf[0] = '\0';
/* both arguments must be absolute paths */
if (start_dir[0] != '/' || finish_dir[0] != '/')
{
errno = EINVAL;
return -1;
}
if (fget_cleanpath(start_dir, buf1, sizeof(buf1)) == -1 ||
fget_cleanpath(finish_dir, buf2, sizeof(buf2)) == -1)
return -1;
/* skip past the common path elements */
do
{
tok1 = strsep(&nextp1, "/");
tok2 = strsep(&nextp2, "/");
}
while (tok1 != NULL && tok2 != NULL && strcmp(tok1, tok2) == 0);
/*
* add ".." elements to get from start_dir back up to the
* directory where the two paths diverge
*/
if (tok1 != NULL)
{
if (strlcat(buf, "..", bufsize) > bufsize)
{
errno = ENAMETOOLONG;
return -1;
}
while ((tok1 = strsep(&nextp1, "/")) != NULL)
{
if (strlcat(buf, "/..", bufsize) > bufsize)
{
errno = ENAMETOOLONG;
return -1;
}
}
}
/* add remaining components from finish_dir */
if (tok2 != NULL)
{
if ((buf[0] != '\0' && strlcat(buf, "/", bufsize) > bufsize)
|| strlcat(buf, tok2, bufsize) > bufsize)
{
errno = ENAMETOOLONG;
return -1;
}
while ((tok2 = strsep(&nextp2, "/")) != NULL)
{
if (strlcat(buf, "/", bufsize) > bufsize
|| strlcat(buf, tok2, bufsize) > bufsize)
{
errno = ENAMETOOLONG;
return -1;
}
}
}
return 0;
}
#ifdef TEST_RELATIVEPATH
int
main(int argc, char *argv[])
{
char buf[MAXPATHLEN];
printf("fget_relativepath(\"%s\", \"%s\") == ", argv[1], argv[2]);
if (fget_relativepath(argv[1], argv[2], buf, sizeof(buf)) == -1)
{
perror("fget_relativepath()");
exit(1);
}
printf("\"%s\"\n", buf);
exit(0);
}
#endif /* TEST_RELATIVEPATH */
syntax highlighted by Code2HTML, v. 0.9.1