/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1989-2012 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* Eduardo Krell <ekrell@adexus.cl> *
* *
***********************************************************************/
#pragma prototyped
#include "3d.h"
#ifndef MAXSYMLINKS
#endif
/*
* if <sp> is a hard link to state.opaque in the same directory then the file
* is opaque and the errno should be ENOENT
*/
static int
{
register char* basesp;
register int r = 0;
return 0;
return 0;
/*
* change the basename to state.opaque
*/
basesp++;
else
{
/*
* for backward compatability
*/
basesp[3] = 0;
goto not_opaque;
}
{
}
else
return r;
}
/*
* return real path name for path
*/
#if DEBUG
char*
{
initialize();
));
return path;
}
#define initialize()
static
#endif
char*
{
register char* sp;
register char* cp;
register char* ip;
int opaqued = 0;
int len;
int vir;
int safesize;
int safe_dir;
long visits;
if (!path)
{
return 0;
}
initialize();
{
return path;
{
return path;
}
return 0;
}
#if FS
#endif
/*
* handle null path, . and / separately
*/
{
type |= P_ABSOLUTE;
}
else
if (!*path)
{
return 0;
}
if (!st)
/*
* check if virtual dir has been created by another process
* only P_PATHONLY|P_TOP calls (usually create or modify link) and
* references to "." are checked for performance
*/
if (state.level > 0 && state.pwd && ((type & (P_PATHONLY|P_TOP)) && *sp != '/' || *sp == '.' && sp[1] == 0))
{
{
len = 0;
goto skip;
}
}
{
return 0;
{
/*
* treat the current directory as if were empty
*/
return 0;
}
else
}
/*
* put absolute pathname into state.path
*/
safe_dir = 0;
if (*path != '/')
{
*sp++ = '/';
if (safe && state.pwdsize >= safesize && !strncmp(state.pwd, state.safe->service, safesize) && (!state.pwd[safesize] || state.pwd[safesize] == '/'))
}
else
sp++;
{
return 0;
}
{
/*
* remove trailing slashes
*/
while (*--ip == '/');
*++ip = 0;
}
*ip++ = '/';
{
/*
* trailing slash is equivalent to trailing slash-dot
* this forces the common-sense interpretation
*/
#if DEBUG
#endif
*ip++ = '.';
*ip = 0;
}
/*
* try to use relative path
*/
{
else
{
{
}
else if (type & P_ABSOLUTE)
else if (*sp == '/')
sp++;
}
if (*sp == 0)
}
skip:
{
opaqued = 1;
}
{
if (cp)
{
goto again;
}
if (!*(sp + 1))
{
}
{
{
return 0;
}
if (sp[1])
else
*buf = 0;
{
return 0;
}
}
else
}
{
return 0;
}
if (type & P_PATHONLY)
{
return sp;
}
visits = 0;
vir = 1;
{
if (vir)
{
{
{
return sp;
}
return 0;
}
vir = 0;
}
{
/*
* check for version instance
*/
return 0;
return 0;
if (*ip == '/')
ip++;
{
cp--;
}
break;
return 0;
}
return 0;
#if FS
/*
* check user mount
*/
if (visits)
{
const char* up;
if ((mp = getmount(sp, &up)) && (mp->fs->flags & FS_NAME) && (sp = fsreal(mp, MSG_open, (char*)up)) && !LSTAT(sp, st))
break;
}
#endif
/*
* search down the viewpath
*/
{
return 0;
}
return 0;
if (!(type & P_ABSOLUTE))
{
/*
* try to use relative path
*/
sp++;
else
}
if (*sp == 0)
}
return 0;
{
int rfd;
int wfd;
sp = 0;
else
{
if (wfd < 0)
sp = 0;
else
{
sp = 0;
}
}
if (!sp)
{
return 0;
}
st = 0;
}
{
{
if (len)
{
*ip = 0;
}
}
{
int mask;
static int gid;
if (uid == -1)
{
}
}
}
/*
* symbolic links handled specially
* get filename from pathname
*/
if (S_ISLNK(st->st_mode) && (len = checklink(sp, st, type)) > 1 && !(type & (P_LSTAT|P_READLINK)) && state.path.nlinks++ < MAXSYMLINKS)
{
if (*path != '/')
goto again;
}
#endif
return sp;
}
/*
* check whether sp points to a version object and find version instance
* sp is canonicalized and points into state.path
* when called from unlink, (type & P_PATHONLY) is set
* -1 for non-existent link
* length of path for a relative link that is not a version object
* 0 otherwise
* state.path.linkname and state.path.linksize are set for version object
*/
int
{
register char* ip;
register int len;
register int n;
register char* bp;
{
message((-1, "AHA#%d checklink bounds sp=%p state.path.name=%p sp=%s", __LINE__, sp, state.path.name, sp));
}
{
/*
* go to the last component
*/
ip++;
else
{
return 0;
}
/*
* check for relative link
*/
if (*ip != '/')
{
{
/*
* version object
*/
ip += n + 4;
{
{
#ifdef S_IFLNK
#endif
return 0;
}
continue;
}
return -1;
}
else if (!(type & (P_LSTAT|P_PATHONLY|P_READLINK)) && *ip == '.' && *(ip + 1) == '.' && (*(ip + 2) == '/' || *(ip + 2) == 0))
{
ip--;
for (;;)
{
ip--;
if (*ip == '/')
ip++;
{
*sp++ = '/';
}
if (*ip == '/')
ip += n;
}
}
}
/*
* restore last component
*/
if (!(type & P_READLINK))
break;
}
return 0;
}