Files
Arquivotheca.SunOS-4.1.4/usr.etc/tfs/libtfs/abspath.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

134 lines
2.6 KiB
C

#ifndef lint
static char sccsid[] = "@(#)abspath.c 1.1 94/10/31 Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/dir.h>
#define MAXSYMLINK 20
/*
* Given any filename, determine its absolute path name guaranteeing
* no symbolic links in the name
*/
char *
nse_abspath(argname, result)
char *argname;
char *result;
{
char relname[MAXPATHLEN];
char tmpname[MAXPATHLEN];
char tmpseg[MAXNAMLEN];
char *relp, *absp;
char *p;
int cc;
char *index(), *rindex();
struct stat stbuf;
int nlink = 0;
char *getwd();
(void) strcpy(relname, argname);
if (relname[0] != '/') {
if (getwd(result) == NULL) /* NOTE: do not use _nse_getwd! */
return ((char *)NULL);
}
checkforroot:
/* see if arg or symlink is relative to root */
relp = relname;
if (*relp == '/') {
result[0] = '\0';
relp++;
}
nextseg:
/* strip leading slashes */
while (*relp == '/')
relp++;
absp = result + strlen(result) - 1;
if (*relp == '\0') {
/* all done - strip trailing slashes */
while (absp > result && *absp == '/')
*absp-- = '\0';
goto out;
}
/* put slash in result if it needs one */
if (absp < result) {
result[0] = '/';
result[1] = '\0';
absp = result;
} else if (*absp != '/') {
*++absp = '/';
*++absp = '\0';
}
/* get next component */
p = index(relp, '/');
if (p) {
(void) strncpy(tmpseg, relp, p-relp);
tmpseg[p-relp] = '\0';
p++;
} else {
(void) strcpy(tmpseg, relp);
p = "";
}
/* "." - nothing changes */
if (strcmp(tmpseg, ".") == 0) {
relp = p;
goto nextseg;
}
/* ".." - strip previous name */
if (strcmp(tmpseg, "..") == 0) {
relp = p;
p = rindex(result, '/');
/* get past trailing slashes */
while (p && p[1] == '\0') {
*p = '\0';
p = rindex(result, '/');
}
if (p == NULL)
p = result;
*p = '\0';
goto nextseg;
}
(void) strcpy(tmpname, result);
(void) strcat(tmpname, tmpseg);
if (lstat(tmpname, &stbuf) != 0) {
(void) strcat(result, relp);
goto out;
}
switch (stbuf.st_mode & S_IFMT) {
case S_IFLNK:
if (++nlink > MAXSYMLINK) {
(void) strcat(result, tmpseg);
relp = p;
goto nextseg;
}
cc = readlink(tmpname, tmpname, sizeof tmpname);
tmpname[cc++] = '/';
tmpname[cc++] = '\0';
(void) strcat(tmpname, p);
(void) strcpy(relname, tmpname);
goto checkforroot;
case S_IFDIR:
(void) strcat(result, tmpseg);
relp = p;
goto nextseg;
default:
(void) strcat(result, relp);
break;
}
out:
if (result[0] == '\0')
(void) strcpy(result, "/");
return (result);
}