Esempio 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;
}
Esempio n. 2
0
File: files.c Progetto: AMDmi3/zsh
static int
recursivecmd(char *nam, int opt_noerr, int opt_recurse, int opt_safe,
    char **args, RecurseFunc dirpre_func, RecurseFunc dirpost_func,
    RecurseFunc leaf_func, void *magic)
{
    int err = 0, len;
    char *rp, *s;
    struct dirsav ds;
    struct recursivecmd reccmd;

    reccmd.nam = nam;
    reccmd.opt_noerr = opt_noerr;
    reccmd.opt_recurse = opt_recurse;
    reccmd.opt_safe = opt_safe;
    reccmd.dirpre_func = dirpre_func;
    reccmd.dirpost_func = dirpost_func;
    reccmd.leaf_func = leaf_func;
    reccmd.magic = magic;
    init_dirsav(&ds);
    if (opt_recurse || opt_safe) {
	if ((ds.dirfd = open(".", O_RDONLY|O_NOCTTY)) < 0 &&
	    zgetdir(&ds) && *ds.dirname != '/')
	    ds.dirfd = open("..", O_RDONLY|O_NOCTTY);
    }
    for(; !errflag && !(err & 2) && *args; args++) {
	rp = ztrdup(*args);
	unmetafy(rp, &len);
	if (opt_safe) {
	    s = strrchr(rp, '/');
	    if (s && !s[1]) {
		while (*s == '/' && s > rp)
		    *s-- = '\0';
		while (*s != '/' && s > rp)
		    s--;
	    }
	    if (s && s[1]) {
		int e;

		*s = '\0';
		e = lchdir(s > rp ? rp : "/", &ds, 1);
		err |= -e;
		if (!e) {
		    struct dirsav d;

		    d.ino = d.dev = 0;
		    d.dirname = NULL;
		    d.dirfd = d.level = -1;
		    err |= recursivecmd_doone(&reccmd, *args, s + 1, &d, 0);
		    zsfree(d.dirname);
		    if (restoredir(&ds))
			err |= 2;
		} else if(!opt_noerr)
		    zwarnnam(nam, "%s: %e", *args, errno);
	    } else
		err |= recursivecmd_doone(&reccmd, *args, rp, &ds, 0);
	} else
	    err |= recursivecmd_doone(&reccmd, *args, rp, &ds, 1);
	zfree(rp, len + 1);
    }
    if ((err & 2) && ds.dirfd >= 0 && restoredir(&ds) && zchdir(pwd)) {
	zsfree(pwd);
	pwd = ztrdup("/");
	if (chdir(pwd) < 0)
	    zwarn("failed to chdir(%s): %e", pwd, errno);
    }
    if (ds.dirfd >= 0)
	close(ds.dirfd);
    zsfree(ds.dirname);
    return !!err;
}