This is realpath.c in view mode; [Download] [Up]
/*
* realpath.c -- canonicalize pathname by removing symlinks
* Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
*
This file is part of XEmacs.
XEmacs is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
XEmacs is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with XEmacs; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Synched up with: Not in FSF. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#if defined(HAVE_UNISTD_H) || defined(STDC_HEADERS)
#include <unistd.h>
#endif
#include <stdio.h>
#include <string.h>
#ifdef _POSIX_VERSION
#include <limits.h> /* for PATH_MAX */
#else
#include <sys/param.h> /* for MAXPATHLEN */
#endif
#include <errno.h>
#ifndef STDC_HEADERS
extern int errno;
#endif
#include <sys/stat.h> /* for S_IFLNK */
#ifndef PATH_MAX
#ifdef _POSIX_VERSION
#define PATH_MAX _POSIX_PATH_MAX
#else
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN
#else
#define PATH_MAX 1024
#endif
#endif
#endif
#define MAX_READLINKS 32
#ifdef __STDC__
char *realpath(const char *path, char resolved_path [])
#else
char *realpath(path, resolved_path)
const char *path;
char resolved_path [];
#endif
{
char copy_path[PATH_MAX];
char link_path[PATH_MAX];
char *new_path = resolved_path;
char *max_path;
int readlinks = 0;
int n;
/* Make a copy of the source path since we may need to modify it. */
strcpy(copy_path, path);
path = copy_path;
max_path = copy_path + PATH_MAX - 2;
/* If it's a relative pathname use getwd for starters. */
if (*path != '/')
{
#ifdef HAVE_GETCWD
getcwd(new_path, PATH_MAX - 1);
#else
getwd(new_path);
#endif
new_path += strlen(new_path);
if (new_path[-1] != '/')
*new_path++ = '/';
}
else
{
*new_path++ = '/';
path++;
}
/* Expand each slash-separated pathname component. */
while (*path != '\0')
{
/* Ignore stray "/". */
if (*path == '/')
{
path++;
continue;
}
if (*path == '.')
{
/* Ignore ".". */
if (path[1] == '\0' || path[1] == '/')
{
path++;
continue;
}
if (path[1] == '.')
{
if (path[2] == '\0' || path[2] == '/')
{
path += 2;
/* Ignore ".." at root. */
if (new_path == resolved_path + 1)
continue;
/* Handle ".." by backing up. */
while ((--new_path)[-1] != '/')
;
continue;
}
}
}
/* Safely copy the next pathname component. */
while (*path != '\0' && *path != '/')
{
if (path > max_path)
{
errno = ENAMETOOLONG;
return NULL;
}
*new_path++ = *path++;
}
#ifdef S_IFLNK
/* See if latest pathname component is a symlink. */
*new_path = '\0';
n = readlink(resolved_path, link_path, PATH_MAX - 1);
if (n < 0)
{
/* EINVAL means the file exists but isn't a symlink. */
if (errno != EINVAL)
return NULL;
}
else
{
/* Protect against infinite loops. */
if (readlinks++ > MAX_READLINKS)
{
errno = ELOOP;
return NULL;
}
/* Note: readlink doesn't add the null byte. */
link_path[n] = '\0';
if (*link_path == '/')
/* Start over for an absolute symlink. */
new_path = resolved_path;
else
/* Otherwise back up over this component. */
while (*(--new_path) != '/')
;
/* Safe sex check. */
if (strlen(path) + n >= PATH_MAX)
{
errno = ENAMETOOLONG;
return NULL;
}
/* Insert symlink contents into path. */
strcat(link_path, path);
strcpy(copy_path, link_path);
path = copy_path;
}
#endif /* S_IFLNK */
*new_path++ = '/';
}
/* Delete trailing slash but don't whomp a lone slash. */
if (new_path != resolved_path + 1 && new_path[-1] == '/')
new_path--;
/* Make sure it's null terminated. */
*new_path = '\0';
return resolved_path;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.