Exemple #1
0
void
fsclunk(Fs *fs, Request *r, Fid *f)
{
	if(f->attached == 0){
		fsreply(fs, r, Enofid);
		return;
	}
	if(f->fd >= 0){
		close(f->fd);
		f->fd = -1;
	}

	if((f->qid.type & QTDIR) == 0)
		closetar(f->df, f->dp);

	releasedf(f->df);
	f->df = nil;
	free(f->dir);
	f->dir = nil;

	fsreply(fs, r, nil);
	fsputfid(fs, f);
}
Exemple #2
0
void
fswalk(Fs *fs, Request *r, Fid *f)
{
	Fid *nf;
	char *name, *tmp;
	int i, nqid, nwname;
	char errbuf[ERRMAX], *err;
	Qid qid[MAXWELEM];
	Dfile *lastdf;
	char *path, *npath;
	Dir *d;
	Symbol *dp;

	if(f->attached == 0){
		fsreply(fs, r, Eexist);
		return;
	}

	if(f->fd >= 0 || f->open)
		fatal("walk of an open file");

	nf = nil;
	if(r->f.newfid != r->f.fid){
		nf = fsgetfid(fs, r->f.newfid);
		nf->attached = 1;
		nf->open = f->open;
		nf->path = strdup(f->path);
		nf->qid = f->qid;
		nf->dp = f->dp;
		nf->fd = f->fd;
		nf->df = f->df;
		if(nf->df){
			lock(nf->df);
			nf->df->use++;
			unlock(nf->df);
		}
		if(r->f.nwname == 0){
			r->f.nwqid = 0;
			fsreply(fs, r, nil);
			return;
		}
		f = nf;
	}

	err = nil;
	path = strdup(f->path);
	if(path == nil)
		fatal(mallocerr);
	nqid = 0;
	nwname = r->f.nwname;
	lastdf = f->df;

	if(nwname > 0){
		for(; nqid<nwname; nqid++){
			name = r->f.wname[nqid];

			if(strcmp(name, ".") == 0){
	Noop:
				if(nqid == 0)
					qid[nqid] = f->qid;
				else
					qid[nqid] = qid[nqid-1];
				continue;
			}

			if(strcmp(name, "..") == 0){
				name = strrchr(path, '/');
				if(name){
					if(name == path)	/* at root */
						goto Noop;
					*name = '\0';
				}
				d = dirstat(path);
				if(d == nil){
					*name = '/';
					errstr(errbuf, sizeof errbuf);
					err = errbuf;
					break;
				}
	Directory:
				qid[nqid] = d->qid;
				free(d);
				releasedf(lastdf);
				lastdf = getdf(mkpath(path, ".depend"));
				continue;
			}

			npath = mkpath(path, name);
			free(path);
			path = npath;
			d = dirstat(path);

			if(d !=nil && (d->qid.type & QTDIR))
				goto Directory;
			free(d);

			qid[nqid].type = QTFILE;
			qid[nqid].path = 0;
			qid[nqid].vers = 0;

			dp = dfsearch(lastdf, name);
			if(dp == nil){
				tmp = strdup(name);
				if(tmp == nil)
					fatal("mallocerr");
				i = strlen(tmp);
				if(i > 4 && strcmp(&tmp[i-4], ".tar") == 0){
					tmp[i-4] = 0;
					dp = dfsearch(lastdf, tmp);
				}
				free(tmp);
			}

			if(dp == nil){
				err = Eexist;
				break;
			}
			qid[nqid].path = (uvlong)dp;
			qid[nqid].vers = 0;
		}
		if(nqid == 0 && err == nil)
			err = "file does not exist";
	}

	/* for error or partial success, put the cloned fid back*/
	if(nf!=nil && (err != nil || nqid < nwname)){
		releasedf(nf->df);
		nf->df = nil;
		fsputfid(fs, nf);
	}

	if(err == nil){
		/* return (possibly short) list of qids */
		for(i=0; i<nqid; i++)
			r->f.wqid[i] = qid[i];
		r->f.nwqid = nqid;

		/* for full success, advance f */
		if(nqid > 0 && nqid == nwname){
			free(f->path);
			f->path = path;
			path = nil;

			f->qid = qid[nqid-1];
			f->dp = (Symbol*)f->qid.path;

			if(f->df != lastdf){
				releasedf(f->df);
				f->df = lastdf;
				lastdf = nil;
			}

		}
	}

	releasedf(lastdf);
	free(path);

	fsreply(fs, r, err);
}
Exemple #3
0
void
fswalk(Fs *fs, Request *r, Fid *f)
{
	char *name;
	int i;
	Dir d;
	char errbuf[ERRLEN];
	char *path;
	Symbol *dp;

	if(f->attached == 0){
		fsreply(fs, r, Enofid);
		return;
	}

	if(f->fd >= 0 || f->open)
		fatal("walk of an open file");

	name = r->f.name;
	if(strcmp(name, ".") == 0){
		fsreply(fs, r, nil);
		return;
	}
	if(strcmp(name, "..") == 0){
		name = strrchr(f->path, '/');
		if(name){
			if(name == f->path){
				fsreply(fs, r, nil);
				return;
			}
			*name = 0;
		}
		if(dirstat(f->path, &d) < 0){
			*name = '/';
			errstr(errbuf);
			fsreply(fs, r, errbuf);
			return;
		}
		r->f.qid = f->qid = d.qid;

		releasedf(f->df);
		f->df = getdf(mkpath(f->path, ".depend"));

		fsreply(fs, r, nil);
		return;
	}

	path = mkpath(f->path, name);
	if(dirstat(path, &d) < 0 || (d.qid.path & CHDIR) == 0){
		dp = dfsearch(f->df, name);
		if(dp == nil){
			i = strlen(name);
			if(i > 4 && strcmp(&name[i-4], ".tar") == 0){
				name[i-4] = 0;
				dp = dfsearch(f->df, name);
			}
		}
		if(dp == nil){
			fsreply(fs, r, Eexist);
			free(path);
			return;
		}
		f->dp = dp;
		d.qid.path = (uint)dp;
		d.qid.vers = 0;
	}

	free(f->path);
	f->path = path;

	if(d.qid.path & CHDIR){
		releasedf(f->df);
		f->df = getdf(mkpath(f->path, ".depend"));
	}

	r->f.qid = f->qid = d.qid;
	fsreply(fs, r, nil);
}
Exemple #4
0
/*
 * Problem is that 9P doesn't allow seeking into a directory.  So we
 * maintain a list of active fids for any given directory.  They
 * start living at the first read and exist either until the directory
 * is closed or until they reach the end.
 */
int
puffs9p_node_readdir(struct puffs_usermount *pu, void *opc, struct dirent *dent,
	off_t *readoff, size_t *reslen, const struct puffs_cred *pcr,
	int *eofflag, off_t *cookies, size_t *ncookies)
{
	AUTOVAR(pu);
	struct puffs_node *pn = opc;
	struct p9pnode *p9n = pn->pn_data;
	struct vattr va;
	struct dirfid *dfp;
	char *name;
	uint32_t count;
	uint16_t statsize;

	rv = getdfwithoffset(pu, p9n, *readoff, &dfp);
	if (rv)
		goto out;

	tag = NEXTTAG(p9p);
	p9pbuf_put_1(pb, P9PROTO_T_READ);
	p9pbuf_put_2(pb, tag);
	p9pbuf_put_4(pb, dfp->fid);
	p9pbuf_put_8(pb, *readoff);
	p9pbuf_put_4(pb, *reslen); /* XXX */
	GETRESPONSE(pb);

	p9pbuf_get_4(pb, &count);

	/*
	 * if count is 0, assume we at end-of-dir.  dfp is no longer
	 * useful, so nuke it
	 */
	if (count == 0) {
		*eofflag = 1;
		releasedf(pu, dfp);
		goto out;
	}

	while (count > 0) {
		if ((rv = proto_getstat(pb, &va, &name, &statsize))) {
			/*
			 * If there was an error, it's unlikely we'll be
			 * coming back, so just nuke the dfp.  If we do
			 * come back for some strange reason, we'll just
			 * regen it.
			 */
			releasedf(pu, dfp);
			goto out;
		}

		puffs_nextdent(&dent, name, va.va_fileid,
		    puffs_vtype2dt(va.va_type), reslen);

		count -= statsize;
		*readoff += statsize;
		dfp->seekoff += statsize;
		free(name);
	}

	storedf(p9n, dfp);

 out:
	RETURN(rv);
}