da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1985-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Glenn Fowler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * pwd library support
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ast.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _WINIX
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinNoN(getcwd)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ast_dir.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <error.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <fs3d.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifndef ERANGE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ERANGE E2BIG
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ERROR(e) { errno = e; goto error; }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct dirlist /* long path chdir(2) component */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct dirlist* next; /* next component */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int index; /* index from end of buf */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * pop long dir component chdir stack
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinpopdir(register struct dirlist* d, register char* end)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct dirlist* dp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int v;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin v = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (dp = d)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin d = d->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!v)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (d) *(end - d->index - 1) = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin v = chdir(end - dp->index);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (d) *(end - d->index - 1) = '/';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(dp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return v;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * push long dir component onto stack
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct dirlist*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinpushdir(register struct dirlist* d, char* dots, char* path, char* end)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct dirlist* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(p = newof(0, struct dirlist, 1, 0)) || chdir(dots))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (p) free(p);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (d) popdir(d, end);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->index = end - path;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->next = d;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return a pointer to the absolute path name of .
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * this path name may be longer than PATH_MAX
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * a few environment variables are checked before the search algorithm
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return value is placed in buf of len chars
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if buf is 0 then space is allocated via malloc() with
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * len extra chars after the path name
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * 0 is returned on error with errno set as appropriate
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinchar*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chingetcwd(char* buf, size_t len)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* d;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin DIR* dirp = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size_t namlen;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ssize_t extra = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct dirent* entry;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct dirlist* dirstk = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct stat* cur;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct stat* par;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct stat* tmp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct stat curst;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct stat parst;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct stat tstst;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char dots[PATH_MAX];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static struct
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* name;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* path;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dev_t dev;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ino_t ino;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } env[] =
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /*previous*/0 },
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { "PWD" },
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { "HOME" },
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin };
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (buf && !len) ERROR(EINVAL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (fs3d(FS3D_TEST) && (namlen = mount(".", dots, FS3D_GET|FS3D_VIEW|FS3D_SIZE(sizeof(dots)), NiL)) > 1 && namlen < sizeof(dots))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p = dots;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin easy:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin namlen++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (buf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (len < namlen) ERROR(ERANGE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!(buf = newof(0, char, namlen, len))) ERROR(ENOMEM);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (char*)memcpy(buf, p, namlen);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cur = &curst;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin par = &parst;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (stat(".", par)) ERROR(errno);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (n = 0; n < elementsof(env); n++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((env[n].name && (p = getenv(env[n].name)) || (p = env[n].path)) && *p == '/' && !stat(p, cur))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env[n].path = p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env[n].dev = cur->st_dev;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env[n].ino = cur->st_ino;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (cur->st_ino == par->st_ino && cur->st_dev == par->st_dev)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin namlen = strlen(p);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto easy;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!buf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin extra = len;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin len = PATH_MAX;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(buf = newof(0, char, len, extra))) ERROR(ENOMEM);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin d = dots;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p = buf + len - 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *p = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = elementsof(env);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (;;)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tmp = cur;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cur = par;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin par = tmp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((d - dots) > (PATH_MAX - 4))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(dirstk = pushdir(dirstk, dots, p, buf + len - 1))) ERROR(ERANGE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin d = dots;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *d++ = '.';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *d++ = '.';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *d = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(dirp = opendir(dots))) ERROR(errno);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_dir_ok || _mem_dd_fd_DIR
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (fstat(dirp->dd_fd, par)) ERROR(errno);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (stat(dots, par)) ERROR(errno);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *d++ = '/';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (par->st_dev == cur->st_dev)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (par->st_ino == cur->st_ino)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin closedir(dirp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *--p = '/';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pop:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (p != buf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin d = buf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*d++ = *p++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin len = d - buf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (extra >= 0 && !(buf = newof(buf, char, len, extra))) ERROR(ENOMEM);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (dirstk && popdir(dirstk, buf + len - 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dirstk = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ERROR(errno);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (env[0].path)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(env[0].path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env[0].path = strdup(buf);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return buf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef D_FILENO
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (entry = readdir(dirp))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (D_FILENO(entry) == cur->st_ino)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin namlen = D_NAMLEN(entry);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto found;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * this fallthrough handles logical naming
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rewinddir(dirp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin do
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(entry = readdir(dirp))) ERROR(ENOENT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin namlen = D_NAMLEN(entry);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((d - dots) > (PATH_MAX - 1 - namlen))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *d = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (namlen >= PATH_MAX || !(dirstk = pushdir(dirstk, dots + 3, p, buf + len - 1))) ERROR(ERANGE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin d = dots + 3;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy(d, entry->d_name, namlen + 1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while (stat(dots, &tstst) || tstst.st_ino != cur->st_ino || tstst.st_dev != cur->st_dev);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin found:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*p) *--p = '/';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while ((p -= namlen) <= (buf + 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin x = (buf + len - 1) - (p += namlen);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = buf + len;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (extra < 0 || !(buf = newof(buf, char, len += PATH_MAX, extra))) ERROR(ERANGE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p = buf + len;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (p > buf + len - 1 - x) *--p = *--s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n < elementsof(env))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy(p, env[n].path, namlen);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto pop;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy(p, entry->d_name, namlen);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin closedir(dirp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dirp = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (n = 0; n < elementsof(env); n++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (env[n].ino == par->st_ino && env[n].dev == par->st_dev)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin namlen = strlen(env[n].path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto found;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (buf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (dirstk) popdir(dirstk, buf + len - 1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (extra >= 0) free(buf);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (dirp) closedir(dirp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif