예제 #1
0
파일: unvac.c 프로젝트: AustenConrad/plan-9
void
unvac(VacFile *f, char *name, VacDir *vdir)
{
	static char buf[65536];
	int fd, n, m,  bsize;
	ulong mode, mode9;
	char *newname;
	char *what;
	vlong off;
	Dir d, *dp;
	VacDirEnum *vde;
	VacDir newvdir;
	VacFile *newf;

	if(vdir)
		mode = vdir->mode;
	else
		mode = vacfilegetmode(f);

	if(vdir){
		if(table){
			if(chatty){
				mode9 = vdir->mode&0777;
				if(mode&ModeDir)
					mode9 |= DMDIR;
				if(mode&ModeAppend)
					mode9 |= DMAPPEND;
				if(mode&ModeExclusive)
					mode9 |= DMEXCL;
				print("%M %-10s %-10s %11lld %t %s\n",
					mode9, vdir->uid, vdir->gid, vdir->size,
					vdir->mtime, name);
			}else
				print("%s%s\n", name, (mode&ModeDir) ? "/" : "");
		}
		else if(chatty)
			fprint(2, "%s%s\n", name, (mode&ModeDir) ? "/" : "");
	}

	if(mode&(ModeDevice|ModeLink|ModeNamedPipe|ModeExclusive)){
		if(table)
			return;
		if(mode&ModeDevice)
			what = "device";
		else if(mode&ModeLink)
			what = "link";
		else if(mode&ModeNamedPipe)
			what = "named pipe";
		else if(mode&ModeExclusive)
			what = "lock";
		else
			what = "unknown type of file";
		fprint(2, "warning: ignoring %s %s\n", what, name);
		return;
	}
	
	if(mode&ModeDir){
		if((vde = vdeopen(f)) == nil){
			fprint(2, "vdeopen %s: %r", name);
			errors++;
			return;
		}
		if(!table && !tostdout && vdir){
			// create directory
			if((dp = dirstat(name)) == nil){
				if((fd = create(name, OREAD, DMDIR|(mode&0777))) < 0){
					fprint(2, "mkdir %s: %r\n", name);
					vdeclose(vde);
				}
				close(fd);
			}else{
				if(!(dp->mode&DMDIR)){
					fprint(2, "%s already exists and is not a directory\n", name);
					errors++;
					free(dp);
					vdeclose(vde);
					return;
				}
				free(dp);
			}
		}
		while(vderead(vde, &newvdir) > 0){
			if(name == nil)
				newname = newvdir.elem;
			else
				newname = smprint("%s/%s", name, newvdir.elem);
			if(wantfile(newname)){
				if((newf = vacfilewalk(f, newvdir.elem)) == nil){
					fprint(2, "walk %s: %r\n", name);
					errors++;
				}else if(newf == f){
					fprint(2, "walk loop: %s\n", newname);
					vacfiledecref(newf);
				}else{
					unvac(newf, newname, &newvdir);
					vacfiledecref(newf);
				}
			}
			if(newname != newvdir.elem)
				free(newname);
			vdcleanup(&newvdir);
		}
		vdeclose(vde);
	}else{
		if(!table){
			off = 0;
			if(tostdout)
				fd = dup(1, -1);
			else if(diff && (fd = open(name, ORDWR)) >= 0){
				bsize = vacfiledsize(f);
				while((n = readn(fd, buf, bsize)) > 0){
					if(sha1matches(f, off/bsize, (uchar*)buf, n)){
						off += n;
						stats.skipdata += n;
						continue;
					}
					seek(fd, off, 0);
					if((m = vacfileread(f, buf, n, off)) < 0)
						break;
					if(writen(fd, buf, m) != m){
						fprint(2, "write %s: %r\n", name);
						goto Err;
					}
					off += m;
					stats.data += m;
					if(m < n){
						nulldir(&d);
						d.length = off;
						if(dirfwstat(fd, &d) < 0){
							fprint(2, "dirfwstat %s: %r\n", name);
							goto Err;
						}
						break;
					}
				}
			}
			else if((fd = create(name, OWRITE, mode&0777)) < 0){
				fprint(2, "create %s: %r\n", name);
				errors++;
				return;
			}
			while((n = vacfileread(f, buf, sizeof buf, off)) > 0){
				if(writen(fd, buf, n) != n){
					fprint(2, "write %s: %r\n", name);
				Err:
					errors++;
					close(fd);
					remove(name);
					return;
				}
				off += n;
				stats.data += n;
			}
			close(fd);
		}
	}
	if(vdir && settimes && !tostdout){
		nulldir(&d);
		d.mtime = vdir->mtime;
		if(dirwstat(name, &d) < 0)
			fprint(2, "warning: setting mtime on %s: %r", name);
	}
}
예제 #2
0
파일: vacfs.c 프로젝트: npe9/harvey
char*
rwalk(Fid *f)
{
	VacFile *file, *nfile;
	Fid *nf;
	int nqid, nwname;
	Qid qid;
	char *err = nil;

	if(f->busy == 0)
		return Enotexist;
	nf = nil;
	if(rhdr.fid != rhdr.newfid){
		if(f->open)
			return vtstrdup(Eisopen);
		if(f->busy == 0)
			return vtstrdup(Enotexist);
		nf = newfid(rhdr.newfid);
		if(nf->busy)
			return vtstrdup(Eisopen);
		nf->busy = 1;
		nf->open = 0;
		nf->qid = f->qid;
		nf->file = vacfileincref(f->file);
		nf->user = vtstrdup(f->user);
		f = nf;
	}

	nwname = rhdr.nwname;

	/* easy case */
	if(nwname == 0) {
		thdr.nwqid = 0;
		return 0;
	}

	file = f->file;
	vacfileincref(file);
	qid = f->qid;

	for(nqid = 0; nqid < nwname; nqid++){
		if((qid.type & QTDIR) == 0){
			err = Enotdir;
			break;
		}
		if(!permf(file, f->user, Pexec)) {
			err = Eperm;
			break;
		}
		nfile = vacfilewalk(file, rhdr.wname[nqid]);
		if(nfile == nil)
			break;
		vacfiledecref(file);
		file = nfile;
		qid.type = QTFILE;
		if(vacfileisdir(file))
			qid.type = QTDIR;
		qid.vers = vacfilegetmcount(file);
		qid.path = vacfilegetid(file);
		thdr.wqid[nqid] = qid;
	}

	thdr.nwqid = nqid;

	if(nqid == nwname){
		/* success */
		f->qid = thdr.wqid[nqid-1];
		vacfiledecref(f->file);
		f->file = file;
		return 0;
	}

	vacfiledecref(file);
	if(nf != nil)
		rclunk(nf);

	/* only error on the first element */
	if(nqid == 0)
		return vtstrdup(err);

	return 0;
}
예제 #3
0
파일: vacfs.c 프로젝트: 00001/plan9port
int
vacstat(VacFile *parent, VacDir *vd, uchar *p, int np)
{
	int ret;
	Dir dir;
#ifdef PLAN9PORT
	int n;
	VacFile *vf;
	uvlong size;
	char *ext = nil;
#endif

	memset(&dir, 0, sizeof(dir));

	dir.qid.path = vd->qid + vacfilegetqidoffset(parent);
	if(vd->qidspace)
		dir.qid.path += vd->qidoffset;
	dir.qid.vers = vd->mcount;
	dir.mode = vd->mode & 0777;
	if(vd->mode & ModeAppend){
		dir.qid.type |= QTAPPEND;
		dir.mode |= DMAPPEND;
	}
	if(vd->mode & ModeExclusive){
		dir.qid.type |= QTEXCL;
		dir.mode |= DMEXCL;
	}
	if(vd->mode & ModeDir){
		dir.qid.type |= QTDIR;
		dir.mode |= DMDIR;
	}
	
#ifdef PLAN9PORT
	if(vd->mode & (ModeLink|ModeDevice|ModeNamedPipe)){
		vf = vacfilewalk(parent, vd->elem);
		if(vf == nil)
			return 0;
		vacfilegetsize(vf, &size);
		ext = malloc(size+1);
		if(ext == nil)
			return 0;
		n = vacfileread(vf, ext, size, 0);
		USED(n);
		ext[size] = 0;
		vacfiledecref(vf);
		if(vd->mode & ModeLink){
			dir.qid.type |= QTSYMLINK;
			dir.mode |= DMSYMLINK;
		}
		if(vd->mode & ModeDevice)
			dir.mode |= DMDEVICE;
		if(vd->mode & ModeNamedPipe)
			dir.mode |= DMNAMEDPIPE;
	}
#endif
	
	dir.atime = vd->atime;
	dir.mtime = vd->mtime;
	dir.length = vd->size;

	dir.name = vd->elem;
	dir.uid = vd->uid;
	dir.gid = vd->gid;
	dir.muid = vd->mid;

	ret = convD2M(&dir, p, np);
#ifdef PLAN9PORT
	free(ext);
#endif
	return ret;
}