Beispiel #1
0
/*
 * Walks elems starting at f.
 * Ok if nelems is 0.
 */
static Path*
walkpath(Memblk *f, char *elems[], int nelems)
{
	int i;
	Memblk *nf;
	Path *p;

	p = newpath(f);
	if(catcherror()){
		putpath(p);
		error(nil);
	}
	isfile(f);
	for(i = 0; i < nelems; i++){
		if((f->d.mode&DMDIR) == 0)
			error("not a directory");
		rwlock(f, Rd);
		if(catcherror()){
			rwunlock(f, Rd);
			error("walk: %r");
		}
		nf = dfwalk(f, elems[i], Rd);
		rwunlock(f, Rd);
		addelem(&p, nf);
		mbput(nf);
		f = nf;
		USED(&f);	/* in case of error() */
		noerror();
	}
	noerror();
	return p;
}
Beispiel #2
0
static void
fsrm(int, char *argv[])
{
	Memblk *f, *pf;
	Path *p;

	p = walkto(argv[1], nil);	
	if(catcherror()){
		putpath(p);
		error(nil);
	}
	if(p->nf < 2)
		error("short path for rm");
	dfmelt(&p, p->nf-1);
	f = p->f[p->nf-1];
	pf = p->f[p->nf-2];
	rwlock(f, Wr);
	if(catcherror()){
		rwunlock(f, Wr);
		rwunlock(pf, Wr);
		error(nil);
	}
	dfremove(pf, f);
	p->f[p->nf-1] = nil;
	noerror();
	noerror();
	rwunlock(pf, Wr);
	putpath(p);
}
Beispiel #3
0
/*
 * Walk to a child and return it referenced.
 * If iswr, d must not be frozen and the child is returned melted.
 */
Memblk*
dfwalk(Memblk *d, char *name, int iswr)
{
	Memblk *f;
	Blksl sl;
	daddrt *de;
	uvlong off;
	int i;
	
	if(strcmp(name, "..") == 0)
		fatal("dfwalk: '..'");
	isdir(d);
	if(iswr)
		ismelted(d);

	off = 0;
	f = nil;
	for(;;){
		sl = dfslice(d, Dblkdatasz, off, Rd);
		if(sl.len == 0){
			assert(sl.b == nil);
			break;
		}
		if(sl.b == nil)
			continue;
		if(catcherror()){
			dprint("dfwalk d%#ullx '%s': %r\n", d->addr, name);
			mbput(sl.b);
			error(nil);
		}
		for(i = 0; i < sl.len/Daddrsz; i++){
			de = sl.data;
			de += i;
			if(*de == 0)
				continue;
			f = dbget(DBfile, *de);
			if(strcmp(f->mf->name, name) != 0){
				mbput(f);
				continue;
			}

			/* found  */
			noerror();
			mbput(sl.b);
			if(!iswr || !f->frozen)
				goto done;
			fatal("dfwalk: frozen");
		}
		noerror();
		mbput(sl.b);
		off += sl.len;
	}
	error("file not found");

done:
	dprint("dfwalk d%#ullx '%s' -> d%#ullx\n", d->addr, name, f->addr);
	return f;
}
Beispiel #4
0
static void
fsget(int, char *argv[])
{
	Memblk *f;
	Mfile *m;
	char buf[4096], *nm;
	uvlong off;
	long nr;
	int fd;
	Path *p;

	fd = create(argv[1], OWRITE, 0664);
	if(fd < 0)
		error("create: %r\n");
	nm = fsname(argv[2]);
	if(catcherror()){
		free(nm);
		close(fd);
		error(nil);
	}
	p = walkto(nm, nil);
	f = p->f[p->nf-1];
	rwlock(f, Rd);
	if(catcherror()){
		rwunlock(f, Rd);
		putpath(p);
		error(nil);
	}
	m = f->mf;
	print("get %-30s\t%M\t%5ulld\t%s %ulld refs\n",
		m->name, (ulong)f->d.mode, f->d.length, m->uid, dbgetref(f->addr));
	if((f->d.mode&DMDIR) == 0){
		off = 0;
		for(;;){
			if(fsmemfree() < Mminfree)
				fslru();
			nr = dfpread(f, buf, sizeof buf, off);
			if(nr <= 0)
				break;
			if(write(fd, buf, nr) != nr){
				fprint(2, "%s: error: %r\n", argv[0]);
				break;
			}
			off += nr;
		}
	}
	close(fd);
	noerror();
	noerror();
	rwunlock(f, Rd);
	putpath(p);
	free(nm);
}
Beispiel #5
0
int
main()
{
    unsigned char outbuf[MAX_ATTRSETSIZE];
    const char *decoded = "accept";
    const char *secret = "foo";
    krb5_error_code retval;
    krb5_context ctx;
    const char *tmp;
    krb5_data in;
    size_t len;

    noerror(krb5_init_context(&ctx));

    /* Make sure User-Name is 1. */
    insist(krad_attr_name2num("User-Name") == 1);

    /* Make sure 2 is User-Password. */
    tmp = krad_attr_num2name(2);
    insist(tmp != NULL);
    insist(strcmp(tmp, "User-Password") == 0);

    /* Test decoding. */
    in = make_data((void *)encoded, sizeof(encoded));
    noerror(kr_attr_decode(ctx, secret, auth,
                           krad_attr_name2num("User-Password"),
                           &in, outbuf, &len));
    insist(len == strlen(decoded));
    insist(memcmp(outbuf, decoded, len) == 0);

    /* Test encoding. */
    in = string2data((char *)decoded);
    retval = kr_attr_encode(ctx, secret, auth,
                            krad_attr_name2num("User-Password"),
                            &in, outbuf, &len);
    insist(retval == 0);
    insist(len == sizeof(encoded));
    insist(memcmp(outbuf, encoded, len) == 0);

    /* Test constraint. */
    in.length = 100;
    insist(kr_attr_valid(krad_attr_name2num("User-Password"), &in) == 0);
    in.length = 200;
    insist(kr_attr_valid(krad_attr_name2num("User-Password"), &in) != 0);

    krb5_free_context(ctx);
    return 0;
}
Beispiel #6
0
static int
ptrmap(daddrt addr, int nind, Blkf f, int isdisk)
{
	int i;
	Memblk *b;
	long tot;

	if(addr == 0)
		return 0;
	if(isdisk)
		b = dbget(DBdata+nind, addr);
	else{
		b = mbget(DBdata+nind, addr, Dontmk);
		if(b == nil)
			return 0;	/* on disk */
	}
	if(catcherror()){
		mbput(b);
		error(nil);
	}
	tot = 0;
	if(f == nil || f(b) == 0){
		tot++;
		if(nind > 0){
			for(i = 0; i < Dptrperblk; i++)
				tot += ptrmap(b->d.ptr[i], nind-1, f, isdisk);
		}
	}
	noerror();
	mbput(b);
	return tot;
}
Beispiel #7
0
/* for dfblk only */
static Memblk*
getmelted(uint isdir, uint type, daddrt *addrp, int *chg)
{
	Memblk *b, *nb;

	*chg = 0;
	if(*addrp == 0){
		b = dballoc(type);
		*addrp = b->addr;
		*chg = 1;
		return b;
	}

	b = dbget(type, *addrp);
	nb = nil;
	if(!b->frozen)
		return b;
	if(catcherror()){
		mbput(b);
		mbput(nb);
		error(nil);
	}
	nb = dbdup(b);
	assert(type == b->type);
	if(isdir && type == DBdata)
		dupdentries(nb->d.data, Dblkdatasz/Daddrsz);
	USED(&nb);		/* for error() */
	*addrp = nb->addr;
	*chg = 1;
	dbput(b, b->type, b->addr);
	noerror();
	mbput(b);
	return nb;
}
Beispiel #8
0
/*
 * Remove [bno:bend) file data blocks.
 * The file must be r/wlocked and melted.
 */
void
dfdropblks(Memblk *f, ulong bno, ulong bend)
{
	Memblk *b;

	isrwlocked(f, Wr);
	ismelted(f);

	dprint("dfdropblks: could remove d%#ullx[%uld:%uld]\n",
		f->addr, bno, bend);
	/*
	 * Instead of releasing the references on the data blocks,
	 * considering that the file might grow again, we keep them.
	 * Consider recompiling again and again and...
	 *
	 * The length has been adjusted and data won't be returned
	 * before overwritten.
	 *
	 * We only have to zero the data, because the file might
	 * grow using holes and the holes must read as zero, and also
	 * for safety.
	 */
	for(; bno < bend; bno++){
		if(catcherror())
			continue;
		b = dfblk(f, bno, Dontmk);
		noerror();
		memset(b->d.data, 0, Dblkdatasz);
		changed(b);
		mbput(b);
	}
}
Beispiel #9
0
static Path*
walkto(char *a, char **lastp)
{
	char *els[Nels], *path;
	int nels;
	Path *p;

	path = fsname(a);
	nels = gettokens(path, els, Nels, "/");
	if(nels < 1){
		free(path);
		error("invalid path");
	}
	if(catcherror()){
		free(path);
		error("walkpath: %r");
	}
	if(lastp != nil){
		p = walkpath(fs->root, els, nels-1);
		*lastp = a + strlen(a) - strlen(els[nels-1]);
	}else
		p = walkpath(fs->root, els, nels);
	free(path);
	noerror();
	if(verb)
		print("walked to %H\n", p->f[p->nf-1]);
	return p;
}
Beispiel #10
0
void
threadmain(int argc, char *argv[])
{
	char *dev;
	char *args[Nels];
	int i, j, nargs;

	dev = "disk";
	ARGBEGIN{
	case 'v':
		verb++;
		break;
	case 'f':
		dev = EARGF(usage());
		break;
	default:
		if(ARGC() >= 'A' && ARGC() <= 'Z'){
			dbg['d'] = 1;
			dbg[ARGC()] = 1;
		}else
			usage();
	}ARGEND;
	if(argc == 0)
		usage();
	fatalaborts = 1;
	fmtinstall('H', mbfmt);
	fmtinstall('M', dirmodefmt);
	errinit(Errstack);
	if(catcherror()){
		fprint(2, "cmd failed: %r\n");
		threadexitsall("failed");
	}
	fsopen(dev);
	for(i = 0; i < argc; i++){
		if(verb>1)
			fsdump(0, Mem);
		print("%% %s\n", argv[i]);
		nargs = gettokens(argv[i], args, Nels, "!");
		for(j = 0; j < nelem(cmds); j++){
			if(strcmp(cmds[j].name, argv[i]) != 0)
				continue;
			if(cmds[j].nargs != 0 && cmds[j].nargs != nargs)
				fprint(2, "usage: %s\n", cmds[j].usage);
			else
				cmds[j].f(nargs, args);
			break;
		}
		if(j == nelem(cmds)){
			fprint(2, "no such command\n");
			for(j = 0; j < nelem(cmds); j++)
				fprint(2, "\t%s\n", cmds[j].usage);
			break;
		}
	}
	if(verb>1)
		fsdump(0, Mem);
	noerror();
	threadexitsall(nil);
}
Beispiel #11
0
long
dfcountrefs(Memblk *f)
{
	Memblk *b;
	int i;
	long nfails;

	nfails = 0;
	isfile(f);
	if((f->addr&Fakeaddr) == 0 && f->addr >= fs->limit){
		fprint(2, "fscheck: '%s' d%#010ullx: out of range\n",
			f->mf->name, f->addr);
		return 1;
	}
	if((f->addr&Fakeaddr) == 0)
		if(countref(f->addr) != 0)		/* already visited */
			return 0;			/* skip children */
	rwlock(f, Rd);
	if(catcherror()){
		fprint(2, "fscheck: '%s' d%#010ullx: data: %r\n",
			f->mf->name, f->addr);
		rwunlock(f, Rd);
		return 1;
	}
	for(i = 0; i < nelem(f->d.dptr); i++)
		ptrmap(f->d.dptr[i], 0, bcountrefs, Disk);
	for(i = 0; i < nelem(f->d.iptr); i++)
		ptrmap(f->d.iptr[i], i+1, bcountrefs, Disk);
	if(f->d.mode&DMDIR)
		for(i = 0; i < f->d.length/Daddrsz; i++){
			b = dfchild(f, i);
			if(catcherror()){
				fprint(2, "fscheck: '%s'  d%#010ullx:"
					" child[%d]: %r\n",
					f->mf->name, f->addr, i);
				nfails++;
			}else{
				nfails += dfcountrefs(b);
				noerror();
			}
			mbput(b);
		}
	noerror();
	rwunlock(f, Rd);
	return nfails;
}
Beispiel #12
0
/*
 * May be called with null parent, for root and ctl files.
 * The first call with a null parent is root, all others are ctl
 * files linked at root.
 */
Memblk*
dfcreate(Memblk *parent, char *name, int uid, ulong mode)
{
	Memblk *nf;
	Mfile *m;
	int isctl;

	if(fsfull())
		error("file system full");
	isctl = parent == nil;
	if(parent == nil)
		parent = fs->root;

	if(parent != nil){
		dprint("dfcreate '%s' %M at\n%H\n", name, mode, parent);
		isdir(parent);
		isrwlocked(parent, Wr);
		ismelted(parent);
	}else
		dprint("dfcreate '%s' %M", name, mode);

	if(isctl)
		nf = dballoc(DBctl);
	else
		nf = dballoc(DBfile);
	if(catcherror()){
		mbput(nf);
		if(parent != nil)
			rwunlock(parent, Wr);
		error(nil);
	}

	m = nf->mf;
	nf->d.id = nsec();
	nf->d.mode = mode;
	nf->d.mtime = nf->d.id;
	nf->d.atime = nf->d.id;
	nf->d.length = 0;
	m->uid = usrname(uid);
	nf->d.uid = uid;
	m->gid = m->uid;
	nf->d.gid = nf->d.uid;
	m->muid = m->uid;
	nf->d.muid = nf->d.uid;
	m->name = name;
	nf->d.asize = pmeta(nf->d.embed, Embedsz, nf);
	changed(nf);

	if(parent != nil){
		m->gid = parent->mf->gid;
		nf->d.gid = parent->d.gid;
		dflink(parent, nf);
	}
	noerror();
	dprint("dfcreate-> %H\n within %H\n", nf, parent);
	return nf;
}
Beispiel #13
0
static void
fscat(int, char *argv[])
{
	Memblk *f;
	Mfile *m;
	char buf[4096], *nm;
	uvlong off;
	long nr;
	Path *p;

	nm = fsname(argv[2]);
	if(catcherror()){
		free(nm);
		error(nil);
	}
	p = walkto(nm, nil);
	f = p->f[p->nf-1];
	rwlock(f, Rd);
	if(catcherror()){
		rwunlock(f, Rd);
		putpath(p);
		error(nil);
	}
	m = f->mf;
	print("cat %-30s\t%M\t%5ulld\t%s %ulld refs\n",
		m->name, (ulong)f->d.mode, f->d.length, m->uid, dbgetref(f->addr));
	if((f->d.mode&DMDIR) == 0){
		off = 0;
		for(;;){
			if(fsmemfree() < Mminfree)
				fslru();
			nr = dfpread(f, buf, sizeof buf, off);
			if(nr <= 0)
				break;
			write(1, buf, nr);
			off += nr;
		}
	}
	noerror();
	noerror();
	rwunlock(f, Rd);
	putpath(p);
	free(nm);
}
Beispiel #14
0
void
dfremove(Memblk *p, Memblk *f)
{
	vlong n;

	/* funny as it seems, we may need extra blocks to melt */
	if(fsfull())
		error("file system full");

	isrwlocked(f, Wr);
	isrwlocked(p, Wr);
	ismelted(p);
	if((f->d.mode&DMDIR) != 0 && f->d.ndents > 0)
		error("directory not empty");
	incref(p);
	if(catcherror()){
		mbput(p);
		error(nil);
	}
	dfunlink(p, f);
	/* shouldn't fail now. it's unlinked */

	if(p->d.ndents == 0 && p->d.length > 0){	/* all gone, make it public */
		p->d.length = 0;
		changed(p);
	}

	noerror();
	rwunlock(f, Wr);
	if(!catcherror()){
		n = dfput(f);
		dprint("dfput d%#ullx: %lld blks\n", f->addr, n);
		noerror();
	}
	mbput(f);
	mbput(p);
}
Beispiel #15
0
static void
fsrm(int, char *argv[])
{
	Memblk *f, *pf;
	Path *p;
	char *nm;

	nm = fsname(argv[1]);
	if(catcherror()){
		free(nm);
		error(nil);
	}
	p = walkto(nm, nil);	
	if(catcherror()){
		putpath(p);
		error(nil);
	}
	if(p->nf < 2)
		error("short path for rm");
	meltedpath(&p, p->nf-1, 1);
	f = p->f[p->nf-1];
	pf = p->f[p->nf-2];
	rwlock(f, Wr);
	if(catcherror()){
		rwunlock(f, Wr);
		rwunlock(pf, Wr);
		error(nil);
	}
	dfremove(pf, f);
	p->f[p->nf-1] = nil;
	noerror();
	noerror();
	noerror();
	rwunlock(pf, Wr);
	putpath(p);
	free(nm);
}
Beispiel #16
0
int
dffreeze(Memblk *f)
{
	int i;
	Memblk *b;
	long tot;

	isfile(f);
	if(f->frozen && f != fs->active && f != fs->archive)
		return 0;
	rwlock(f, Wr);
	if(catcherror()){
		rwunlock(f, Wr);
		error(nil);
	}
	f->frozen = 1;
	tot = 1;
	for(i = 0; i < nelem(f->d.dptr); i++)
		tot += ptrmap(f->d.dptr[i], 0, bfreeze, Mem);
	for(i = 0; i < nelem(f->d.iptr); i++)
		tot += ptrmap(f->d.iptr[i], i+1, bfreeze, Mem);
	if((f->d.mode&DMDIR) != 0){
		for(i = 0; i < f->d.length/Daddrsz; i++){
			b = mfchild(f, i);
			if(b == nil)
				continue;
			if(!catcherror()){
				tot += dffreeze(b);
				noerror();
			}
			mbput(b);
		}
	}
	noerror();
	rwunlock(f, Wr);
	return tot;
}
Beispiel #17
0
/*
 * Drop one disk reference for f and reclaim its storage if it's gone.
 * The given memory reference is not released.
 * For directories, all files contained have their disk references adjusted,
 * and they are also reclaimed if no further references exist.
 *
 * NB: Time ago, directories were not in compact form (they had holes
 * due to removals) and this had a bug while reclaiming that could lead
 * to double frees of disk blocks.
 * The bug was fixed, but since then, directories have changed again to
 * have holes. If the a double free happens again, this is the place where
 * to look, besides dbdup and dfchdentry.
 */
int
dfput(Memblk *f)
{
	int i;
	Memblk *b;
	long tot;

	isfile(f);
	dKprint("dfput %H\n", f);
	/*
	 * Remove children if it's the last disk ref before we drop data blocks.
	 * No new disk refs may be added, so there's no race here.
	 */
	tot = 0;
	if(dbgetref(f->addr) == 1 && (f->d.mode&DMDIR) != 0){
		rwlock(f, Wr);
		if(catcherror()){
			rwunlock(f, Wr);
			error(nil);
		}
		for(i = 0; i < f->d.ndents; i++){
			b = dfchild(f, i);
			if(!catcherror()){
				tot += dfput(b);
				noerror();
			}
			mbput(b);
		}
		noerror();
		rwunlock(f, Wr);
	}

	if(dbput(f, f->type, f->addr) == 0)
		tot++;
	return tot;
}
Beispiel #18
0
/*
 * Report that a file has been modified.
 * Modification times propagate up to the root of the file tree.
 * But frozen files are never changed.
 */
void
dfchanged(Path *p, int muid)
{
	Memblk *f;
	u64int t, u;
	int i;

	t = nsec();
	u = muid;
	for(i = 0; i < p->nf; i++){
		f = p->f[i];
		rwlock(f, Wr);
		if(f->frozen == 0)
			if(!catcherror()){
				f->d.mtime = t;
				f->d.atime = t;
				f->d.muid = muid;
				changed(f);
				noerror();
			}
		rwunlock(f, Wr);
	}
}
Beispiel #19
0
/*
 * CAUTION: debug: no locks.
 */
int
dfdump(Memblk *f, int isdisk)
{
	int i;
	Memblk *b;
	Memblk *(*child)(Memblk*, int);
	long tot;
	extern int mbtab;

	isfile(f);
	tot = 1;
	/* visit the blocks to fetch them if needed. */
	for(i = 0; i < nelem(f->d.dptr); i++)
		tot += ptrmap(f->d.dptr[i], 0, nil, isdisk);
	for(i = 0; i < nelem(f->d.iptr); i++)
		tot += ptrmap(f->d.iptr[i], i+1, nil, isdisk);
	fprint(2, "%H\n", f);
	if((f->d.mode&DMDIR) != 0){
		mbtab++;
		child = dfchild;
		if(!isdisk)
			child = mfchild;
		for(i = 0; i < f->d.ndents; i++){
			b = child(f, i);
			if(b == nil)
				continue;
			if(!catcherror()){
				tot += dfdump(b, isdisk);
				noerror();
			}
			mbput(b);
		}
		mbtab--;
	}

	return tot;
}
Beispiel #20
0
/*
 * Find a dir entry for addr (perhaps 0 == avail) and change it to
 * naddr. If iswr, the entry is allocated if needed and the blocks
 * melted on demand.
 * Return the offset for the entry in the file or Noaddr
 * Does not adjust disk refs.
 */
uvlong
dfchdentry(Memblk *d, u64int addr, u64int naddr, int mkit)
{
	Blksl sl;
	daddrt *de;
	uvlong off;
	int i;

	assert(d->d.length/Daddrsz >= d->d.ndents);

	dAprint("dfchdentry d%#ullx -> d%#ullx\nin %H\n", addr, naddr, d);
	isrwlocked(d, mkit?Wr:Rd);
	isdir(d);

	if(addr == naddr)
		fatal("dfchdentry: it did happen. now, why?");

	off = 0;

	for(;;){
		sl = dfslice(d, Dblkdatasz, off, mkit);
		if(sl.len == 0){
			assert(sl.b == nil);
			break;
		}
		if(sl.b == nil){
			if(addr == 0 && !mkit)
				return off;
			continue;
		}
		if(catcherror()){
			mbput(sl.b);
			error(nil);
		}
		de = sl.data;
		for(i = 0; i < sl.len/Daddrsz; i++){
			if(de[i] == addr){
				off += i*Daddrsz;
				if(naddr != addr){
					de[i] = naddr;
					changed(sl.b);
					if(addr == 0 && naddr != 0){
						if(d->d.length < off+Daddrsz)
							d->d.length = off+Daddrsz;
						d->d.ndents++;
						changed(d);
					}else if(addr != 0 && naddr == 0){
						d->d.ndents--;
						changed(d);
					}
				}
				noerror();
				mbput(sl.b);
				assert(d->d.length/Daddrsz >= d->d.ndents);
				return off;
			}
		}
		off += sl.len;
		noerror();
		mbput(sl.b);
	}
	if(mkit)
		fatal("dfchdentry: bug");
	return Noaddr;
}
Beispiel #21
0
/*
 * This is unrealistic in that it keeps the file locked
 * during the entire put. This means that we can only give
 * fslru() a chance before each put, and not before each
 * write, because everything is going to be in use and dirty if
 * we run out of memory.
 */
static void
fsput(int, char *argv[])
{
	int fd;
	char *fn;
	Memblk *m, *f;
	Dir *d;
	char buf[4096];
	uvlong off;
	long nw, nr;
	Path *p;
	char *nm;

	fd = open(argv[1], OREAD);
	if(fd < 0)
		error("open: %r\n");
	d = dirfstat(fd);
	if(d == nil){
		error("dirfstat: %r\n");
	}
	nm = fsname(argv[2]);
	if(catcherror()){
		free(nm);
		close(fd);
		free(d);
		error(nil);
	}
	p = walkto(nm, &fn);
	if(catcherror()){
		putpath(p);
		error(nil);
	}
	meltedpath(&p, p->nf, 1);
	m = p->f[p->nf-1];
	if(catcherror()){
		rwunlock(m, Wr);
		error(nil);
	}
	f = dfcreate(m, fn, usrid(d->uid), d->mode&(DMDIR|0777));
	noerror();
	addelem(&p, f);
	decref(f);	/* kept now in p */
	rwlock(f, Wr);
	rwunlock(m, Wr);
	if(catcherror()){
		rwunlock(f, Wr);
		error(nil);
	}
	if((d->mode&DMDIR) == 0){
		off = 0;
		for(;;){
			if(fsmemfree() < Mminfree)
				fslru();
			nr = read(fd, buf, sizeof buf);
			if(nr <= 0)
				break;
			nw = dfpwrite(f, buf, nr, &off);
			dprint("wrote %ld of %ld bytes\n", nw, nr);
			off += nr;
		}
	}
	noerror();
	noerror();
	noerror();
	if(verb)
		print("created %H\nat %H\n", f, m);
	rwunlock(f, Wr);
	free(nm);
	putpath(p);
	close(fd);
	free(d);
}
Beispiel #22
0
void Indexer::import() {
        int total = 0;
    QStringList filePaths;
    ProgressionInfo informations;
    informations.style = searching;
    informations.phrase = QString(tr("Recherche de morceaux en cours..."));
    emit updateBar(informations);

    iterator = new QDirIterator(chemin, filtre, QDir::NoFilter, QDirIterator::Subdirectories);

    while(iterator->hasNext()) {

        if(loopRunning == false) {
            return;

        }

        filePaths.append(iterator->next());
        total++;
        ProgressionInfo informations;
        informations.phrase = QString(tr("%1 morceaux trouvés")).arg(total);
        informations.style = searching;
        emit updateBar(informations);
    }

    if(loopRunning == false) {
        return;
    }

    if(filePaths.count() == 0) {

        emit fatalError(tr("Aucun fichier trouvé dans le dossier spécifié"));
    }

    QString noerror(tr("0 medias importés")), alreadyexists(tr("0 existent déjà")), error(tr("aucune erreur"));
    int o = 0; //nombre d'erreurs
    int a = 0;
    for(int i = 0;i<filePaths.count();i++) {

        if(loopRunning == false || filePaths.count() == 0 || i == filePaths.count()) {

            return;
        }

        NutshMetaData data(filePaths.value(i));
        errorcode = saver->inserer(data);


        switch(errorcode) {

            case NoError:
                qDebug() << "NoError";
                noerror = QString(tr("%1 medias importés")).arg(i-a-o);
            break;
            case SqlError:
                qDebug() << "SqlError";
                o = o+1;
                error = QString(tr("%1 erreurs")).arg(o);
            break;
            case CantDecodeTag:
                qDebug() << "CantDecodeTag";
                o = o+1;
                error = QString(tr("%1 erreurs")).arg(o);
            break;
            case AlreadyExists:
                qDebug() << "AlreadyExists";
                a = a+1;
                alreadyexists = QString(tr("%1 doublons")).arg(a);
            break;
        }
        ProgressionInfo informations;
        informations.progression = i+1;
        informations.maximum = total;
        informations.phrase = QString("%1, %2").arg(noerror).arg(alreadyexists);
        informations.style = progression;

        emit updateBar(informations);

    }
    emit loopEnded();
}
Beispiel #23
0
/*
 * Get a file data block, perhaps allocating it on demand
 * if mkit. The file must be r/wlocked and melted if mkit.
 *
 * Adds disk refs for dir entries copied during melts and
 * considers that /archive is always melted.
 *
 * Read-ahead is not considered here. The file only records
 * the last accessed block number, to help the caller do RA.
 *
 */
static Memblk*
dfblk(Memblk *f, ulong bno, int mkit)
{
	ulong prev, nblks;
	int i, idx, nindir, type, isdir, chg;
	Memblk *b, *pb;
	daddrt *addrp;

	if(mkit)
		ismelted(f);
	isdir = (f->d.mode&DMDIR);

	if(bno != f->mf->lastbno){
		f->mf->sequential = (!mkit && bno == f->mf->lastbno + 1);
		f->mf->lastbno = bno;
	}

	/*
	 * bno: block # relative to the the block we are looking at.
	 * prev: # of blocks before the current one.
	 */
	prev = 0;
	chg = 0;

	/*
	 * Direct block?
	 */
	if(bno < nelem(f->d.dptr)){
		if(mkit)
			b = getmelted(isdir, DBdata, &f->d.dptr[bno], &chg);
		else
			b = dbget(DBdata, f->d.dptr[bno]);
		if(chg)
			changed(f);
		return b;
	}
	bno -= nelem(f->d.dptr);
	prev += nelem(f->d.dptr);

	/*
	 * Indirect block
	 * nblks: # of data blocks addressed by the block we look at.
	 */
	nblks = Dptrperblk;
	for(i = 0; i < nelem(f->d.iptr); i++){
		if(bno < nblks)
			break;
		bno -= nblks;
		prev += nblks;
		nblks *= Dptrperblk;
	}
	if(i == nelem(f->d.iptr))
		error("offset exceeds file capacity");
	ainc(&fs->nindirs[i]);
	type = DBptr0+i;
	dFprint("dfblk: indirect %s nblks %uld (ppb %ud) bno %uld\n",
		tname(type), nblks, Dptrperblk, bno);

	addrp = &f->d.iptr[i];
	if(mkit)
		b = getmelted(isdir, type, addrp, &chg);
	else
		b = dbget(type, *addrp);
	if(chg)
		changed(f);
	pb = b;
	if(catcherror()){
		mbput(pb);
		error(nil);
	}

	/* at the loop header:
	 * 	pb: parent of b
	 * 	b: DBptr block we are looking at.
	 * 	addrp: ptr to b within fb.
	 * 	nblks: # of data blocks addressed by b
	 */
	for(nindir = i+1; nindir >= 0; nindir--){
		chg = 0;
		dFprint("indir %s d%#ullx nblks %uld ptrperblk %d bno %uld\n\n",
			tname(DBdata+nindir), *addrp, nblks, Dptrperblk, bno);
		idx = 0;
		if(nindir > 0){
			nblks /= Dptrperblk;
			idx = bno/nblks;
		}
		if(*addrp == 0 && !mkit){
			/* hole */
			fprint(2, "HOLE\n");
			b = nil;
		}else{
			assert(type >= DBdata);
			if(mkit)
				b = getmelted(isdir, type, addrp, &chg);
			else
				b = dbget(type, *addrp);
			if(chg)
				changed(pb);
			addrp = &b->d.ptr[idx];
		}
		mbput(pb);
		pb = b;
		USED(&b);	/* force to memory in case of error */
		USED(&pb);	/* force to memory in case of error */
		bno -= idx * nblks;
		prev +=  idx * nblks;
		type--;
	}
	noerror();

	return b;
}
Beispiel #24
0
/*
 * Caller walked down p, and now requires the nth element to be
 * melted, and wlocked for writing. (nth count starts at 1);
 * 
 * Return the path with the version of f that we must use,
 * locked for writing and melted.
 * References kept in the path are traded for the ones returned.
 */
Path*
dfmelt(Path **pp, int nth)
{
	int i;
	Memblk *f, **fp, *nf;
	Path *p;

	ownpath(pp);
	p = *pp;
	assert(nth >= 1 && p->nf >= nth && p->nf >= 2);
	assert(p->f[0] == fs->root);
	fp = &p->f[nth-1];

	/*
	 * 1. Optimistic: Try to get a loaded melted version for f.
	 */
	followmelted(fp, Wr);
	f = *fp;
	if(!f->frozen)
		return p;
	ainc(&fs->nmelts);
	rwunlock(f, Wr);

	/*
	 * 2. Realistic:
	 * walk down the path, melting every frozen thing until we
	 * reach f. Keep wlocks so melted files are not frozen while we walk.
	 * /active is special, because it's only frozen temporarily while
	 * creating a frozen version of the tree. Instead of melting it,
	 * we should just wait for it.
	 * p[0] is /
	 * p[1] is /active
	 */
	for(;;){
		followmelted(&p->f[1], Wr);
		if(p->f[1]->frozen == 0)
			break;
		rwunlock(p->f[1], Wr);
		yield();
	}
	/*
	 * At loop header, parent is p->f[i-1], melted and wlocked.
	 * At the end of the loop, p->f[i] is melted and wlocked.
	 */
	for(i = 2; i < nth; i++){
		followmelted(&p->f[i], Wr);
		if(!p->f[i]->frozen){
			rwunlock(p->f[i-1], Wr);
			continue;
		}
		if(catcherror()){
			rwunlock(p->f[i-1], Wr);
			rwunlock(p->f[i], Wr);
			error(nil);
		}

		nf = dbdup(p->f[i]);
		rwlock(nf, Wr);

		if(catcherror()){
			rwunlock(nf, Wr);
			mbput(nf);
			error(nil);
		}
		dfchdentry(p->f[i-1], p->f[i]->addr, nf->addr, Mkit);
		noerror();
		noerror();
		/* committed */
		rwunlock(p->f[i-1], Wr);		/* parent */
		rwunlock(p->f[i], Wr);		/* old frozen version */
		f = p->f[i];
		p->f[i] = nf;
		assert(f->ref > 1);
		mbput(f);			/* ref from path */
		if(!catcherror()){
			dbput(f, f->type, f->addr); /* p->f[i] ref from disk */
			noerror();
		}
	}
	return p;
}