Exemplo n.º 1
0
mod_export char *
zgetdir(struct dirsav *d)
{
    char nbuf[PATH_MAX+3];
    char *buf;
    int bufsiz, pos;
    struct stat sbuf;
    ino_t pino;
    dev_t pdev;
#if !defined(__CYGWIN__) && !defined(USE_GETCWD)
    struct dirent *de;
    DIR *dir;
    dev_t dev;
    ino_t ino;
    int len;
#endif

    buf = zhalloc(bufsiz = PATH_MAX);
    pos = bufsiz - 1;
    buf[pos] = '\0';
    strcpy(nbuf, "../");
    if (stat(".", &sbuf) < 0) {
	return NULL;
    }

    /* Record the initial inode and device */
    pino = sbuf.st_ino;
    pdev = sbuf.st_dev;
    if (d)
	d->ino = pino, d->dev = pdev;
#if !defined(__CYGWIN__) && !defined(USE_GETCWD)
#ifdef HAVE_FCHDIR
    else
#endif
	holdintr();

    for (;;) {
	/* Examine the parent of the current directory. */
	if (stat("..", &sbuf) < 0)
	    break;

	/* Inode and device of curtent directory */
	ino = pino;
	dev = pdev;
	/* Inode and device of current directory's parent */
	pino = sbuf.st_ino;
	pdev = sbuf.st_dev;

	/* If they're the same, we've reached the root directory. */
	if (ino == pino && dev == pdev) {
	    if (!buf[pos])
		buf[--pos] = '/';
	    if (d) {
#ifndef HAVE_FCHDIR
		zchdir(buf + pos);
		noholdintr();
#endif
		return d->dirname = ztrdup(buf + pos);
	    }
	    zchdir(buf + pos);
	    noholdintr();
	    return buf + pos;
	}

	/* Search the parent for the current directory. */
	if (!(dir = opendir("..")))
	    break;

	while ((de = readdir(dir))) {
	    char *fn = de->d_name;
	    /* Ignore `.' and `..'. */
	    if (fn[0] == '.' &&
		(fn[1] == '\0' ||
		 (fn[1] == '.' && fn[2] == '\0')))
		continue;
#ifdef HAVE_STRUCT_DIRENT_D_STAT
	    if(de->d_stat.st_dev == dev && de->d_stat.st_ino == ino) {
		/* Found the directory we're currently in */
		strncpy(nbuf + 3, fn, PATH_MAX);
		break;
	    }
#else /* !HAVE_STRUCT_DIRENT_D_STAT */
# ifdef HAVE_STRUCT_DIRENT_D_INO
	    if (dev != pdev || (ino_t) de->d_ino == ino)
# endif /* HAVE_STRUCT_DIRENT_D_INO */
	    {
		/* Maybe found directory, need to check device & inode */
		strncpy(nbuf + 3, fn, PATH_MAX);
		lstat(nbuf, &sbuf);
		if (sbuf.st_dev == dev && sbuf.st_ino == ino)
		    break;
	    }
#endif /* !HAVE_STRUCT_DIRENT_D_STAT */
	}
	closedir(dir);
	if (!de)
	    break;		/* Not found */
	/*
	 * We get the "/" free just by copying from nbuf+2 instead
	 * of nbuf+3, which is where we copied the path component.
	 * This means buf[pos] is always a "/".
	 */
	len = strlen(nbuf + 2);
	pos -= len;
	while (pos <= 1) {
	    char *newbuf = zhalloc(2*bufsiz);
	    memcpy(newbuf + bufsiz, buf, bufsiz);
	    buf = newbuf;
	    pos += bufsiz;
	    bufsiz *= 2;
	}
	memcpy(buf + pos, nbuf + 2, len);
#ifdef HAVE_FCHDIR
	if (d)
	    return d->dirname = ztrdup(buf + pos + 1);
#endif
	if (chdir(".."))
	    break;
    }

    /*
     * Fix up the directory, if necessary.
     * We're changing back down the hierarchy, ignore the
     * "/" at buf[pos].
     */
    if (d) {
#ifndef HAVE_FCHDIR
	if (buf[pos])
	    zchdir(buf + pos + 1);
	noholdintr();
#endif
	return NULL;
    }

    if (buf[pos])
	zchdir(buf + pos + 1);
    noholdintr();

#else  /* __CYGWIN__, USE_GETCWD cases */

    if (!getcwd(buf, bufsiz)) {
	if (d) {
	    return NULL;
	}
    } else {
	if (d) {
	    return d->dirname = ztrdup(buf);
	}
	return buf;
    }
#endif

    /*
     * Something bad happened.
     * This has been seen when inside a special directory,
     * such as the Netapp .snapshot directory, that doesn't
     * appear as a directory entry in the parent directory.
     * We'll just need our best guess.
     *
     * We only get here from zgetcwd(); let that fall back to pwd.
     */

    return NULL;
}
Exemplo n.º 2
0
char *
zgetcwd(void)
{
    static char buf0[PATH_MAX];
#if defined(_WIN32)
    getcwd(buf0, PATH_MAX);
    return ztrdup(buf0);
#else
    char *buf2 = buf0 + 1;
    char buf3[PATH_MAX];
    struct stat sbuf;
    struct dirent *de;
    DIR *dir;
    ino_t ino, pino, rootino = (ino_t) ~ 0;
    dev_t dev, pdev, rootdev = (dev_t) ~ 0;

    holdintr();
    buf2[0] = '\0';
    buf0[0] = '/';

    if (stat(buf0, &sbuf) >= 0) {
	rootino = sbuf.st_ino;
	rootdev = sbuf.st_dev;
    }

    if (stat(".", &sbuf) < 0) {
	noholdintr();
	return ztrdup(".");
    }

    pino = sbuf.st_ino;
    pdev = sbuf.st_dev;

    for (;;) {
	if (stat("..", &sbuf) < 0) {
	    chdir(buf0);
	    noholdintr();
	    return ztrdup(".");
	}

	ino = pino;
	dev = pdev;
	pino = sbuf.st_ino;
	pdev = sbuf.st_dev;

	if ((ino == pino && dev == pdev) ||
	    (ino == rootino && dev == rootdev)) {
	    chdir(buf0);
	    noholdintr();
	    return ztrdup(buf0);
	}
	dir = opendir("..");
	if (!dir) {
	    chdir(buf0);
	    noholdintr();
	    return ztrdup(".");
	}
	chdir("..");
	while ((de = readdir(dir))) {
	    char *fn = de->d_name;
	    /* Ignore `.' and `..'. */
	    if (fn[0] == '.' &&
		(fn[1] == '\0' ||
		 (fn[1] == '.' && fn[2] == '\0')))
		continue;
	    if (dev != pdev || (ino_t) de->d_ino == ino) {
		lstat(fn, &sbuf);
		if (sbuf.st_dev == dev && sbuf.st_ino == ino) {
		    strcpy(buf3, de->d_name);
		    break;
		}
	    }
	}
	closedir(dir);
	if (!de) {
	    noholdintr();
	    return ztrdup(".");
	}
	if (*buf2)
	    strcat(buf3, "/");
	strcat(buf3, buf2);
	strcpy(buf2, buf3);
    }
#endif
}