/* 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