Ejemplo n.º 1
0
Archivo: fs.c Proyecto: bhanug/harvey
int
fsVac(Fs *fs, char *name, uint8_t score[VtScoreSize])
{
	int r;
	DirEntry de;
	Entry e, ee;
	File *f;

	vtRLock(fs->elk);
	f = fileOpen(fs, name);
	if(f == nil){
		vtRUnlock(fs->elk);
		return 0;
	}

	if(!fileGetSources(f, &e, &ee) || !fileGetDir(f, &de)){
		fileDecRef(f);
		vtRUnlock(fs->elk);
		return 0;
	}
	fileDecRef(f);

	r = mkVac(fs->z, fs->blockSize, &e, &ee, &de, score);
	vtRUnlock(fs->elk);
	return r;
}
Ejemplo n.º 2
0
int
fileMetaFlush(File *f, int rec)
{
	File **kids, *p;
	int nkids;
	int i, rv;

	fileMetaLock(f);
	rv = fileMetaFlush2(f, nil);
	fileMetaUnlock(f);

	if(!rec || !fileIsDir(f))
		return rv;

	if(!fileLock(f))
		return rv;
	nkids = 0;
	for(p=f->down; p; p=p->next)
		nkids++;
	kids = vtMemAlloc(nkids*sizeof(File*));
	i = 0;
	for(p=f->down; p; p=p->next){
		kids[i++] = p;
		p->ref++;
	}
	fileUnlock(f);

	for(i=0; i<nkids; i++){
		rv |= fileMetaFlush(kids[i], 1);
		fileDecRef(kids[i]);
	}
	vtMemFree(kids);
	return rv;
}
Ejemplo n.º 3
0
int
usersFileRead(char* path)
{
	char *p;
	File *file;
	Fsys *fsys;
	int len, r;
	uvlong size;

	if((fsys = fsysGet("main")) == nil)
		return 0;
	fsysFsRlock(fsys);

	if(path == nil)
		path = "/active/adm/users";

	r = 0;
	if((file = fileOpen(fsysGetFs(fsys), path)) != nil){
		if(fileGetSize(file, &size)){
			len = size;
			p = vtMemAlloc(size+1);
			if(fileRead(file, p, len, 0) == len){
				p[len] = '\0';
				r = uboxInit(p, len);
			}
		}
		fileDecRef(file);
	}

	fsysFsRUnlock(fsys);
	fsysPut(fsys);

	return r;
}
Ejemplo n.º 4
0
Archivo: fs.c Proyecto: bhanug/harvey
static int
fsNeedArch(Fs *fs, uint archMinute)
{
	int need;
	File *f;
	char buf[100];
	Tm now;
	uint32_t then;

	then = time(0);
	now = *localtime(then);

	/* back up to yesterday if necessary */
	if(now.hour < archMinute/60
	|| now.hour == archMinute/60 && now.min < archMinute%60)
		now = *localtime(then-86400);

	snprint(buf, sizeof buf, "/archive/%d/%02d%02d",
		now.year+1900, now.mon+1, now.mday);
	need = 1;
	vtRLock(fs->elk);
	f = fileOpen(fs, buf);
	if(f){
		need = 0;
		fileDecRef(f);
	}
	vtRUnlock(fs->elk);
	return need;
}
Ejemplo n.º 5
0
static int
clri(File *f, char *uid)
{
	int r;

	if(f == nil)
		return 0;
	if(f->up->source->mode != OReadWrite){
		vtSetError(EReadOnly);
		fileDecRef(f);
		return 0;
	}
	r = fileMetaRemove(f, uid);
	fileDecRef(f);
	return r;
}
Ejemplo n.º 6
0
Archivo: fs.c Proyecto: bhanug/harvey
/* return number of directory entries remaining */
static int
fsRsearch1(File *f, char *s)
{
	int n, r;
	DirEntry de;
	DirEntryEnum *dee;
	File *ff;
	char *t;

	dee = deeOpen(f);
	if(dee == nil)
		return 0;

	n = 0;
	for(;;){
		r = deeRead(dee, &de);
		if(r <= 0)
			break;
		n++;
		if(de.mode & ModeSnapshot){
			if((ff = fileWalk(f, de.elem)) != nil)
				fileDecRef(ff);
			else if(strcmp(vtGetError(), ESnapOld) == 0){
				if(fileClri(f, de.elem, "adm"))
					n--;
			}
		}
		else if(de.mode & ModeDir){
			if((ff = fileWalk(f, de.elem)) != nil){
				t = smprint("%s/%s", s, de.elem);
				if(fsRsearch1(ff, t) == 0)
					if(fileRemove(ff, "adm"))
						n--;
				vtMemFree(t);
				fileDecRef(ff);
			}
		}
		deCleanup(&de);
		if(r < 0)
			break;
	}
	deeClose(dee);

	return n;
}
Ejemplo n.º 7
0
Archivo: fs.c Proyecto: bhanug/harvey
static int
fsEsearch1(File *f, char *path, uint32_t savetime, uint32_t *plo)
{
	int n, r;
	DirEntry de;
	DirEntryEnum *dee;
	File *ff;
	Entry e, ee;
	char *t;

	dee = deeOpen(f);
	if(dee == nil)
		return 0;

	n = 0;
	for(;;){
		r = deeRead(dee, &de);
		if(r <= 0)
			break;
		if(de.mode & ModeSnapshot){
			if((ff = fileWalk(f, de.elem)) != nil){
				if(fileGetSources(ff, &e, &ee))
					if(de.mtime >= savetime && e.snap != 0)
						if(e.snap < *plo)
							*plo = e.snap;
				fileDecRef(ff);
			}
		}
		else if(de.mode & ModeDir){
			if((ff = fileWalk(f, de.elem)) != nil){
				t = smprint("%s/%s", path, de.elem);
				n += fsEsearch1(ff, t, savetime, plo);
				vtMemFree(t);
				fileDecRef(ff);
			}
		}
		deCleanup(&de);
		if(r < 0)
			break;
	}
	deeClose(dee);

	return n;
}
Ejemplo n.º 8
0
static void
addFile(File *root, char *name, uint mode)
{
	File *f;

	f = fileCreate(root, name, mode | ModeDir, "adm");
	if(f == nil)
		vtFatal("could not create file: %s: %r", name);
	fileDecRef(f);
}
Ejemplo n.º 9
0
void
deeClose(DirEntryEnum *dee)
{
	int i;
	if(dee == nil)
		return;
	for(i=dee->i; i<dee->n; i++)
		deCleanup(dee->buf+i);
	vtMemFree(dee->buf);
	fileDecRef(dee->file);
	vtMemFree(dee);
}
Ejemplo n.º 10
0
File *
_fileOpen(Fs *fs, char *path, int partial)
{
	File *f, *ff;
	char *p, elem[VtMaxStringSize], *opath;
	int n;

	f = fs->file;
	fileIncRef(f);
	opath = path;
	while(*path != 0){
		for(p = path; *p && *p != '/'; p++)
			;
		n = p - path;
		if(n > 0){
			if(n > VtMaxStringSize){
				vtSetError("%s: element too long", EBadPath);
				goto Err;
			}
			memmove(elem, path, n);
			elem[n] = 0;
			ff = _fileWalk(f, elem, partial && *p=='\0');
			if(ff == nil){
				vtSetError("%.*s: %R", utfnlen(opath, p-opath),
					opath);
				goto Err;
			}
			fileDecRef(f);
			f = ff;
		}
		if(*p == '/')
			p++;
		path = p;
	}
	return f;
Err:
	fileDecRef(f);
	return nil;
}
Ejemplo n.º 11
0
Archivo: 9fid.c Proyecto: 99years/plan9
static void
fidFree(Fid* fid)
{
	if(fid->file != nil){
		fileDecRef(fid->file);
		fid->file = nil;
	}
	if(fid->db != nil){
		dirBufFree(fid->db);
		fid->db = nil;
	}
	fidUnlock(fid);

	if(fid->uid != nil){
		vtMemFree(fid->uid);
		fid->uid = nil;
	}
	if(fid->uname != nil){
		vtMemFree(fid->uname);
		fid->uname = nil;
	}
	if(fid->excl != nil)
		exclFree(fid);
	if(fid->rpc != nil){
		close(fid->rpc->afd);
		auth_freerpc(fid->rpc);
		fid->rpc = nil;
	}
	if(fid->fsys != nil){
		fsysPut(fid->fsys);
		fid->fsys = nil;
	}
	if(fid->cuname != nil){
		vtMemFree(fid->cuname);
		fid->cuname = nil;
	}

	vtLock(fbox.lock);
	fbox.inuse--;
	if(fbox.nfree < 10){
		fid->hash = fbox.free;
		fbox.free = fid;
		fbox.nfree++;
	}
	else{
		vtLockFree(fid->alock);
		vtLockFree(fid->lock);
		vtMemFree(fid);
	}
	vtUnlock(fbox.lock);
}
Ejemplo n.º 12
0
Archivo: fs.c Proyecto: bhanug/harvey
static int
fsRsearch(Fs *fs, char *path)
{
	File *f;
	DirEntry de;

	f = fileOpen(fs, path);
	if(f == nil)
		return 0;
	if(!fileGetDir(f, &de)){
		fileDecRef(f);
		return 0;
	}
	if((de.mode & ModeDir) == 0){
		fileDecRef(f);
		deCleanup(&de);
		return 0;
	}
	deCleanup(&de);
	fsRsearch1(f, path);
	fileDecRef(f);
	return 1;
}
Ejemplo n.º 13
0
Archivo: fs.c Proyecto: bhanug/harvey
static int
fsEsearch(Fs *fs, char *path, uint32_t savetime, uint32_t *plo)
{
	int n;
	File *f;
	DirEntry de;

	f = fileOpen(fs, path);
	if(f == nil)
		return 0;
	if(!fileGetDir(f, &de)){
		fileDecRef(f);
		return 0;
	}
	if((de.mode & ModeDir) == 0){
		fileDecRef(f);
		deCleanup(&de);
		return 0;
	}
	deCleanup(&de);
	n = fsEsearch1(f, path, savetime, plo);
	fileDecRef(f);
	return n;
}
Ejemplo n.º 14
0
Archivo: fs.c Proyecto: bhanug/harvey
void
fsClose(Fs *fs)
{
	vtRLock(fs->elk);
	periodicKill(fs->metaFlush);
	snapClose(fs->snap);
	if(fs->file){
		fileMetaFlush(fs->file, 0);
		if(!fileDecRef(fs->file))
			vtFatal("fsClose: files still in use: %r\n");
	}
	fs->file = nil;
	sourceClose(fs->source);
	cacheFree(fs->cache);
	if(fs->arch)
		archFree(fs->arch);
	vtMemFree(fs->name);
	vtRUnlock(fs->elk);
	vtLockFree(fs->elk);
	memset(fs, ~0, sizeof(Fs));
	vtMemFree(fs);
}
Ejemplo n.º 15
0
int
fileDecRef(File *f)
{
	File *p, *q, **qq;

	if(f->up == nil){
		/* never linked in */
		assert(f->ref == 1);
		fileFree(f);
		return 1;
	}

	fileMetaLock(f);
	f->ref--;
	if(f->ref > 0){
		fileMetaUnlock(f);
		return 0;
	}
	assert(f->ref == 0);
	assert(f->down == nil);

	fileMetaFlush2(f, nil);

	p = f->up;
	qq = &p->down;
	for(q = *qq; q; q = *qq){
		if(q == f)
			break;
		qq = &q->next;
	}
	assert(q != nil);
	*qq = f->next;

	fileMetaUnlock(f);
	fileFree(f);

	fileDecRef(p);
	return 1;
}
Ejemplo n.º 16
0
static void
topLevel(char *name)
{
	Fs *fs;
	File *root;

	/* ok, now we can open as a fs */
	fs = fsOpen(name, z, 100, OReadWrite);
	if(fs == nil)
		vtFatal("could not open file system: %r");
	vtRLock(fs->elk);
	root = fsGetRoot(fs);
	if(root == nil)
		vtFatal("could not open root: %r");
	addFile(root, "active", 0555);
	addFile(root, "archive", 0555);
	addFile(root, "snapshot", 0555);
	fileDecRef(root);
	if(iso9660file)
		iso9660copy(fs);
	vtRUnlock(fs->elk);
	fsClose(fs);
}
Ejemplo n.º 17
0
/*
 * convert File* to full path name in malloced string.
 * this hasn't been as useful as we hoped it would be.
 */
char *
fileName(File *f)
{
	char *name, *pname;
	File *p;
	static char root[] = "/";

	if (f == nil)
		return vtStrDup("/**GOK**");

	p = fileGetParent(f);
	if (p == f)
		name = vtStrDup(root);
	else {
		pname = fileName(p);
		if (strcmp(pname, root) == 0)
			name = smprint("/%s", f->dir.elem);
		else
			name = smprint("%s/%s", pname, f->dir.elem);
		free(pname);
	}
	fileDecRef(p);
	return name;
}
Ejemplo n.º 18
0
DirEntryEnum *
deeOpen(File *f)
{
	DirEntryEnum *dee;
	File *p;

	if(!fileIsDir(f)){
		vtSetError(ENotDir);
		fileDecRef(f);
		return nil;
	}

	/* flush out meta data */
	if(!fileLock(f))
		return nil;
	for(p=f->down; p; p=p->next)
		fileMetaFlush2(p, nil);
	fileUnlock(f);

	dee = vtMemAllocZ(sizeof(DirEntryEnum));
	dee->file = fileIncRef(f);

	return dee;
}
Ejemplo n.º 19
0
static int
usersFileWrite(Ubox* box)
{
	Fs *fs;
	User *u;
	int i, r;
	Fsys *fsys;
	char *p, *q, *s;
	File *dir, *file;

	if((fsys = fsysGet("main")) == nil)
		return 0;
	fsysFsRlock(fsys);
	fs = fsysGetFs(fsys);

	/*
	 * BUG:
	 * 	the owner/group/permissions need to be thought out.
	 */
	r = 0;
	if((dir = fileOpen(fs, "/active")) == nil)
		goto tidy0;
	if((file = fileWalk(dir, uidadm)) == nil)
		file = fileCreate(dir, uidadm, ModeDir|0775, uidadm);
	fileDecRef(dir);
	if(file == nil)
		goto tidy;
	dir = file;
	if((file = fileWalk(dir, "users")) == nil)
		file = fileCreate(dir, "users", 0664, uidadm);
	fileDecRef(dir);
	if(file == nil)
		goto tidy;
	if(!fileTruncate(file, uidadm))
		goto tidy;

	p = s = vtMemAlloc(box->len+1);
	q = p + box->len+1;
	for(u = box->head; u != nil; u = u->next){
		p += snprint(p, q-p, "%s:%s:", u->uid, u->uname);
		if(u->leader != nil)
			p+= snprint(p, q-p, u->leader);
		p += snprint(p, q-p, ":");
		if(u->ngroup){
			p += snprint(p, q-p, u->group[0]);
			for(i = 1; i < u->ngroup; i++)
				p += snprint(p, q-p, ",%s", u->group[i]);
		}
		p += snprint(p, q-p, "\n");
	}
	r = fileWrite(file, s, box->len, 0, uidadm);
	vtMemFree(s);

tidy:
	if(file != nil)
		fileDecRef(file);
tidy0:
	fsysFsRUnlock(fsys);
	fsysPut(fsys);

	return r;
}
Ejemplo n.º 20
0
int
fileSetDir(File *f, DirEntry *dir, char *uid)
{
	File *ff;
	char *oelem;
	u32int mask;
	u64int size;

	/* can not set permissions for the root */
	if(fileIsRoot(f)){
		vtSetError(ERoot);
		return 0;
	}

	if(!fileLock(f))
		return 0;

	if(f->source->mode != OReadWrite){
		vtSetError(EReadOnly);
		fileUnlock(f);
		return 0;
	}

	fileMetaLock(f);

	/* check new name does not already exist */
	if(strcmp(f->dir.elem, dir->elem) != 0){
		for(ff = f->up->down; ff; ff=ff->next){
			if(strcmp(dir->elem, ff->dir.elem) == 0 && !ff->removed){
				vtSetError(EExists);
				goto Err;
			}
		}

		ff = dirLookup(f->up, dir->elem);
		if(ff != nil){
			fileDecRef(ff);
			vtSetError(EExists);
			goto Err;
		}
	}

	if(!sourceLock2(f->source, f->msource, -1))
		goto Err;
	if(!fileIsDir(f)){
		size = sourceGetSize(f->source);
		if(size != dir->size){
			if(!sourceSetSize(f->source, dir->size)){
				sourceUnlock(f->source);
				if(f->msource)
					sourceUnlock(f->msource);
				goto Err;
			}
			/* commited to changing it now */
		}
	}
	/* commited to changing it now */
	if((f->dir.mode&ModeTemporary) != (dir->mode&ModeTemporary))
		fileSetTmp(f, dir->mode&ModeTemporary);
	sourceUnlock(f->source);
	if(f->msource)
		sourceUnlock(f->msource);

	oelem = nil;
	if(strcmp(f->dir.elem, dir->elem) != 0){
		oelem = f->dir.elem;
		f->dir.elem = vtStrDup(dir->elem);
	}

	if(strcmp(f->dir.uid, dir->uid) != 0){
		vtMemFree(f->dir.uid);
		f->dir.uid = vtStrDup(dir->uid);
	}

	if(strcmp(f->dir.gid, dir->gid) != 0){
		vtMemFree(f->dir.gid);
		f->dir.gid = vtStrDup(dir->gid);
	}

	f->dir.mtime = dir->mtime;
	f->dir.atime = dir->atime;

//fprint(2, "mode %x %x ", f->dir.mode, dir->mode);
	mask = ~(ModeDir|ModeSnapshot);
	f->dir.mode &= ~mask;
	f->dir.mode |= mask & dir->mode;
	f->dirty = 1;
//fprint(2, "->%x\n", f->dir.mode);

	fileMetaFlush2(f, oelem);
	vtMemFree(oelem);

	fileMetaUnlock(f);
	fileUnlock(f);

	fileWAccess(f->up, uid);

	return 1;
Err:
	fileMetaUnlock(f);
	fileUnlock(f);
	return 0;
}
Ejemplo n.º 21
0
File *
fileCreate(File *f, char *elem, ulong mode, char *uid)
{
	File *ff;
	DirEntry *dir;
	Source *pr, *r, *mr;
	int isdir;

	if(!fileLock(f))
		return nil;

	r = nil;
	mr = nil;
	for(ff = f->down; ff; ff=ff->next){
		if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){
			ff = nil;
			vtSetError(EExists);
			goto Err1;
		}
	}

	ff = dirLookup(f, elem);
	if(ff != nil){
		vtSetError(EExists);
		goto Err1;
	}

	pr = f->source;
	if(pr->mode != OReadWrite){
		vtSetError(EReadOnly);
		goto Err1;
	}

	if(!sourceLock2(f->source, f->msource, -1))
		goto Err1;

	ff = fileAlloc(f->fs);
	isdir = mode & ModeDir;

	r = sourceCreate(pr, pr->dsize, isdir, 0);
	if(r == nil)
		goto Err;
	if(isdir){
		mr = sourceCreate(pr, pr->dsize, 0, r->offset);
		if(mr == nil)
			goto Err;
	}

	dir = &ff->dir;
	dir->elem = vtStrDup(elem);
	dir->entry = r->offset;
	dir->gen = r->gen;
	if(isdir){
		dir->mentry = mr->offset;
		dir->mgen = mr->gen;
	}
	dir->size = 0;
	if(!fsNextQid(f->fs, &dir->qid))
		goto Err;
	dir->uid = vtStrDup(uid);
	dir->gid = vtStrDup(f->dir.gid);
	dir->mid = vtStrDup(uid);
	dir->mtime = time(0L);
	dir->mcount = 0;
	dir->ctime = dir->mtime;
	dir->atime = dir->mtime;
	dir->mode = mode;

	ff->boff = fileMetaAlloc(f, dir, 0);
	if(ff->boff == NilBlock)
		goto Err;

	sourceUnlock(f->source);
	sourceUnlock(f->msource);

	ff->source = r;
	r->file = ff;			/* point back */
	ff->msource = mr;

	if(mode&ModeTemporary){
		if(!sourceLock2(r, mr, -1))
			goto Err1;
		fileSetTmp(ff, 1);
		sourceUnlock(r);
		if(mr)
			sourceUnlock(mr);
	}

	/* committed */

	/* link in and up parent ref count */
	ff->next = f->down;
	f->down = ff;
	ff->up = f;
	fileIncRef(f);

	fileWAccess(f, uid);

	fileUnlock(f);
	return ff;

Err:
	sourceUnlock(f->source);
	sourceUnlock(f->msource);
Err1:
	if(r){
		sourceLock(r, -1);
		sourceRemove(r);
	}
	if(mr){
		sourceLock(mr, -1);
		sourceRemove(mr);
	}
	if(ff)
		fileDecRef(ff);
	fileUnlock(f);
	return 0;
}
Ejemplo n.º 22
0
Archivo: fs.c Proyecto: bhanug/harvey
int
fsSnapshot(Fs *fs, char *srcpath, char *dstpath, int doarchive)
{
	File *src, *dst;

	assert(fs->mode == OReadWrite);

	dst = nil;

	if(fs->halted){
		vtSetError("file system is halted");
		return 0;
	}

	/*
	 * Freeze file system activity.
	 */
	vtLock(fs->elk);

	/*
	 * Get the root of the directory we're going to save.
	 */
	if(srcpath == nil)
		srcpath = "/active";
	src = fileOpen(fs, srcpath);
	if(src == nil)
		goto Err;

	/*
	 * It is important that we maintain the invariant that:
	 *	if both b and bb are marked as Active with start epoch e
	 *	and b points at bb, then no other pointers to bb exist.
	 * 
	 * When bb is unlinked from b, its close epoch is set to b's epoch.
	 * A block with epoch == close epoch is
	 * treated as free by cacheAllocBlock; this aggressively
	 * reclaims blocks after they have been stored to Venti.
	 *
	 * Let's say src->source is block sb, and src->msource is block
	 * mb.  Let's also say that block b holds the Entry structures for
	 * both src->source and src->msource (their Entry structures might
	 * be in different blocks, but the argument is the same).
	 * That is, right now we have:
	 *
	 *	b	Active w/ epoch e, holds ptrs to sb and mb.
	 *	sb	Active w/ epoch e.
	 *	mb	Active w/ epoch e.
	 *
	 * With things as they are now, the invariant requires that
	 * b holds the only pointers to sb and mb.  We want to record
	 * pointers to sb and mb in new Entries corresponding to dst,
	 * which breaks the invariant.  Thus we need to do something
	 * about b.  Specifically, we bump the file system's epoch and
	 * then rewalk the path from the root down to and including b.
	 * This will copy-on-write as we walk, so now the state will be:
	 *
	 *	b	Snap w/ epoch e, holds ptrs to sb and mb.
	 *	new-b	Active w/ epoch e+1, holds ptrs to sb and mb.
	 *	sb	Active w/ epoch e.
	 *	mb	Active w/ epoch e.
	 *
	 * In this state, it's perfectly okay to make more pointers to sb and mb.
	 */
	if(!bumpEpoch(fs, 0) || !fileWalkSources(src))
		goto Err;

	/*
	 * Sync to disk.  I'm not sure this is necessary, but better safe than sorry.
	 */
	cacheFlush(fs->cache, 1);

	/*
	 * Create the directory where we will store the copy of src.
	 */
	dst = fileOpenSnapshot(fs, dstpath, doarchive);
	if(dst == nil)
		goto Err;

	/*
	 * Actually make the copy by setting dst's source and msource
	 * to be src's.
	 */
	if(!fileSnapshot(dst, src, fs->ehi-1, doarchive))
		goto Err;

	fileDecRef(src);
	fileDecRef(dst);
	src = nil;
	dst = nil;

	/*
	 * Make another copy of the file system.  This one is for the
	 * archiver, so that the file system we archive has the recently
	 * added snapshot both in /active and in /archive/yyyy/mmdd[.#].
	 */
	if(doarchive){
		if(!saveQid(fs))
			goto Err;
		if(!bumpEpoch(fs, 1))
			goto Err;
	}

	vtUnlock(fs->elk);

	/* BUG? can fs->arch fall out from under us here? */
	if(doarchive && fs->arch)
		archKick(fs->arch);

	return 1;

Err:
	fprint(2, "%s: fsSnapshot: %R\n", argv0);
	if(src)
		fileDecRef(src);
	if(dst)
		fileDecRef(dst);
	vtUnlock(fs->elk);
	return 0;
}
Ejemplo n.º 23
0
File *
_fileWalk(File *f, char *elem, int partial)
{
	File *ff;

	fileRAccess(f);

	if(elem[0] == 0){
		vtSetError(EBadPath);
		return nil;
	}

	if(!fileIsDir(f)){
		vtSetError(ENotDir);
		return nil;
	}

	if(strcmp(elem, ".") == 0){
		return fileIncRef(f);
	}

	if(strcmp(elem, "..") == 0){
		if(fileIsRoot(f))
			return fileIncRef(f);
		return fileIncRef(f->up);
	}

	if(!fileLock(f))
		return nil;

	for(ff = f->down; ff; ff=ff->next){
		if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){
			ff->ref++;
			goto Exit;
		}
	}

	ff = dirLookup(f, elem);
	if(ff == nil)
		goto Err;

	if(ff->dir.mode & ModeSnapshot){
		ff->mode = OReadOnly;
		ff->issnapshot = 1;
	}

	if(partial){
		/*
		 * Do nothing.  We're opening this file only so we can clri it.
		 * Usually the sources can't be opened, hence we won't even bother.
		 * Be VERY careful with the returned file.  If you hand it to a routine
		 * expecting ff->source and/or ff->msource to be non-nil, we're
		 * likely to dereference nil.  FileClri should be the only routine
		 * setting partial.
		 */
		ff->partial = 1;
	}else if(ff->dir.mode & ModeDir){
		ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen,
			1, ff->mode, ff->issnapshot);
		ff->msource = fileOpenSource(f, ff->dir.mentry, ff->dir.mgen,
			0, ff->mode, ff->issnapshot);
		if(ff->source == nil || ff->msource == nil)
			goto Err;
	}else{
		ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen,
			0, ff->mode, ff->issnapshot);
		if(ff->source == nil)
			goto Err;
	}

	/* link in and up parent ref count */
	if (ff->source)
		ff->source->file = ff;		/* point back */
	ff->next = f->down;
	f->down = ff;
	ff->up = f;
	fileIncRef(f);
Exit:
	fileUnlock(f);
	return ff;
Err:
	fileUnlock(f);
	if(ff != nil)
		fileDecRef(ff);
	return nil;
}
Ejemplo n.º 24
0
Archivo: fs.c Proyecto: bhanug/harvey
/*
 * Prepare the directory to store a snapshot.
 * Temporary snapshots go into /snapshot/yyyy/mmdd/hhmm[.#]
 * Archival snapshots go into /archive/yyyy/mmdd[.#].
 *
 * TODO This should be rewritten to eliminate most of the duplication.
 */
static File*
fileOpenSnapshot(Fs *fs, char *dstpath, int doarchive)
{
	int n;
	char buf[30], *s, *p, *elem;
	File *dir, *f;
	Tm now;

	if(dstpath){
		if((p = strrchr(dstpath, '/')) != nil){
			*p++ = '\0';
			elem = p;
			p = dstpath;
			if(*p == '\0')
				p = "/";
		}else{
			p = "/";
			elem = dstpath;
		}
		if((dir = fileOpen(fs, p)) == nil)
			return nil;
		f = fileCreate(dir, elem, ModeDir|ModeSnapshot|0555, "adm");
		fileDecRef(dir);
		return f;
	}else if(doarchive){
		/*
		 * a snapshot intended to be archived to venti.
		 */
		dir = fileOpen(fs, "/archive");
		if(dir == nil)
			return nil;
		now = *localtime(time(0));

		/* yyyy */
		snprint(buf, sizeof(buf), "%d", now.year+1900);
		f = fileWalk(dir, buf);
		if(f == nil)
			f = fileCreate(dir, buf, ModeDir|0555, "adm");
		fileDecRef(dir);
		if(f == nil)
			return nil;
		dir = f;

		/* mmdd[#] */
		snprint(buf, sizeof(buf), "%02d%02d", now.mon+1, now.mday);
		s = buf+strlen(buf);
		for(n=0;; n++){
			if(n)
				seprint(s, buf+sizeof(buf), ".%d", n);
			f = fileWalk(dir, buf);
			if(f != nil){
				fileDecRef(f);
				continue;
			}
			f = fileCreate(dir, buf, ModeDir|ModeSnapshot|0555, "adm");
			break;
		}
		fileDecRef(dir);
		return f;
	}else{
		/*
		 * Just a temporary snapshot
		 * We'll use /snapshot/yyyy/mmdd/hhmm.
		 * There may well be a better naming scheme.
		 * (I'd have used hh:mm but ':' is reserved in Microsoft file systems.)
		 */
		dir = fileOpen(fs, "/snapshot");
		if(dir == nil)
			return nil;

		now = *localtime(time(0));

		/* yyyy */
		snprint(buf, sizeof(buf), "%d", now.year+1900);
		f = fileWalk(dir, buf);
		if(f == nil)
			f = fileCreate(dir, buf, ModeDir|0555, "adm");
		fileDecRef(dir);
		if(f == nil)
			return nil;
		dir = f;

		/* mmdd */
		snprint(buf, sizeof(buf), "%02d%02d", now.mon+1, now.mday);
		f = fileWalk(dir, buf);
		if(f == nil)
			f = fileCreate(dir, buf, ModeDir|0555, "adm");
		fileDecRef(dir);
		if(f == nil)
			return nil;
		dir = f;

		/* hhmm[.#] */
		snprint(buf, sizeof buf, "%02d%02d", now.hour, now.min);
		s = buf+strlen(buf);
		for(n=0;; n++){
			if(n)
				seprint(s, buf+sizeof(buf), ".%d", n);
			f = fileWalk(dir, buf);
			if(f != nil){
				fileDecRef(f);
				continue;
			}
			f = fileCreate(dir, buf, ModeDir|ModeSnapshot|0555, "adm");
			break;
		}
		fileDecRef(dir);
		return f;
	}
}