Esempio n. 1
0
/*
 * Occasionally, pathnames are created that look like .../x/../y
 * Any of the 'x/..' sequences within the name can be eliminated.
 * (but only if 'x' is not a symbolic link!!)
 */
void remove_dotdot(char *path)
{
    char    *end, *from, *to, **cp;
    char    *components[ MAXFILES ],
            newpath[ BUFSIZ ];
    boolean     component_copied;

    /*
     * slice path up into components.
     */
    to = newpath;
    if (*path == '/')
        *to++ = '/';
    *to = '\0';
    cp = components;
    for (from=end=path; *end; end++)
        if (*end == '/') {
            while (*end == '/')
                *end++ = '\0';
            if (*from)
                *cp++ = from;
            from = end;
        }
    *cp++ = from;
    *cp = NULL;

    /*
     * Recursively remove all 'x/..' component pairs.
     */
    cp = components;
    while(*cp) {
        if (!isdot(*cp) && !isdotdot(*cp) && isdotdot(*(cp+1))
            && !issymbolic(newpath, *cp))
        {
            char **fp = cp + 2;
            char **tp = cp;

            do {
              *tp++ = *fp; /* move all the pointers down */
            } while (*fp++);
            if (cp != components)
            cp--;   /* go back and check for nested ".." */
        } else {
            cp++;
        }
    }
    /*
     * Concatenate the remaining path elements.
     */
    cp = components;
    component_copied = FALSE;
    while(*cp) {
        if (component_copied)
            *to++ = '/';
        component_copied = TRUE;
        for (from = *cp; *from; )
            *to++ = *from++;
        *to = '\0';
        cp++;
    }
    *to++ = '\0';

    /*
     * copy the reconstituted path back to our pointer.
     */
    strcpy(path, newpath);
}
Esempio n. 2
0
static int
vnop_lookup_9p(struct vnop_lookup_args *ap)
{
	struct componentname *cnp;
	node_9p *dnp;
	vnode_t *vpp, dvp;
	fid_9p fid;
	qid_9p qid;
	int e;

	TRACE();
	dvp = ap->a_dvp;
	vpp = ap->a_vpp;
	cnp = ap->a_cnp;
	dnp = NTO9P(dvp);

	if(!vnode_isdir(dvp))
		return ENOTDIR;

	if (isdotdot(cnp) && vnode_isvroot(dvp))
		return EIO;

	if (islastcn(cnp) && !isop(cnp, LOOKUP) && vnode_vfsisrdonly(dvp))
		return EROFS;

	if (isdot(cnp)) {
		if (islastcn(cnp) && isop(cnp, RENAME))
			return EISDIR;

		if ((e=vnode_get(dvp)))
			return e;
		*vpp = dvp;
		return 0;
	}

	if (isdotdot(cnp)) {
		*vpp = vnode_getparent(dvp);
		if (*vpp == NULL)
			return ENOENT;
		return 0;
	}

	e = cache_lookup(dvp, vpp, cnp);
	if (e == -1)	/* found */
		return 0;
	if (e != 0)		/* errno */
		return e;

	/* not in cache */
	nlock_9p(dnp, NODE_LCK_EXCLUSIVE);
	e = walk_9p(dnp->nmp, dnp->fid, cnp->cn_nameptr, cnp->cn_namelen, &fid, &qid);
	if (e) {
		if (islastcn(cnp)) {
			if (isop(cnp, CREATE) || isop(cnp, RENAME))
				e = EJUSTRETURN;
			else if (ismkentry(cnp) && dnp->dir.qid.vers!=0)
				cache_enter(dvp, NULL, cnp);
		}
		goto error;
	}

	e = nget_9p(dnp->nmp, fid, qid, dvp, vpp, cnp, ap->a_context);
	if (e || *vpp==NULL || NTO9P(*vpp)->fid!=fid) 
		clunk_9p(dnp->nmp, fid);

	if (*vpp)
		nunlock_9p(NTO9P(*vpp));

error:
	nunlock_9p(dnp);
	return e;
}
Esempio n. 3
0
File: devfs.c Progetto: 8l/inferno
Walkqid*
fswalk(Chan *c, Chan *nc, char **name, int nname)
{
	int j, alloc;
	Walkqid *wq;
	Dir *dir;
	char *n;
	Cname *current, *next;
	Qid rootqid;

	if(nname > 0)
		isdir(c);	/* do we need this? */

	alloc = 0;
	current = nil;
	wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
	if(waserror()){
		if(alloc && wq->clone!=nil)
			cclose(wq->clone);
		cnameclose(current);
		free(wq);
		return nil;
	}
	if(nc == nil){
		nc = devclone(c);
		nc->type = 0;
		alloc = 1;
	}
	wq->clone = nc;

	rootqid = FS(c)->rootqid;
	current = FS(c)->name;
	if(current != nil)
		incref(&current->r);
	for(j=0; j<nname; j++){
		if(!(nc->qid.type&QTDIR)){
			if(j==0)
				error(Enotdir);
			break;
		}
		n = name[j];
		if(strcmp(n, ".") != 0 && !(isdotdot(n) && nc->qid.path == rootqid.path)){	/* TO DO: underlying qids aliased */
			//print("** ufs walk '%s' -> %s\n", current->s, n);
			next = current;
			incref(&next->r);
			next = addelem(current, n);
			dir = dirstat(next->s);
			if(dir == nil){
				cnameclose(next);
				if(j == 0)
					error(Enonexist);
				strcpy(up->env->errstr, Enonexist);
				break;
			}
			nc->qid = dir->qid;
			free(dir);
			cnameclose(current);
			current = next;
		}
		wq->qid[wq->nqid++] = nc->qid;
	}
//	print("** ufs walk '%s'\n", current->s);

	poperror();
	if(wq->nqid < nname){
		cnameclose(current);
		if(alloc)
			cclose(wq->clone);
		wq->clone = nil;
	}else if(wq->clone){
		/* now attach to our device */
		nc->aux = smalloc(sizeof(Fsinfo));
		nc->type = c->type;
		FS(nc)->rootqid = FS(c)->rootqid;
		FS(nc)->name = current;
		FS(nc)->fd = -1;
		FS(nc)->root = FS(c)->root;
	}else
		panic("fswalk: can't happen");
	return wq;
}