xref: /plan9/sys/src/cmd/sam/disk.c (revision 59cc4ca53493a3c6d2349fe2b7f7c40f7dce7294)
17dd7cddfSDavid du Colombier #include "sam.h"
27dd7cddfSDavid du Colombier 
37dd7cddfSDavid du Colombier static	Block	*blist;
47dd7cddfSDavid du Colombier 
57dd7cddfSDavid du Colombier static int
67dd7cddfSDavid du Colombier tempdisk(void)
77dd7cddfSDavid du Colombier {
87dd7cddfSDavid du Colombier 	char dir[DIRLEN];
97dd7cddfSDavid du Colombier 	char buf[128];
107dd7cddfSDavid du Colombier 	int i, fd;
117dd7cddfSDavid du Colombier 
12*59cc4ca5SDavid du Colombier 	snprint(buf, sizeof buf, "/tmp/X%d.%.4ssam", getpid(), getuser());
137dd7cddfSDavid du Colombier 	for(i='A'; i<='Z'; i++){
147dd7cddfSDavid du Colombier 		buf[5] = i;
157dd7cddfSDavid du Colombier 		if(stat(buf, dir) == 0)
167dd7cddfSDavid du Colombier 			continue;
177dd7cddfSDavid du Colombier 		fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
187dd7cddfSDavid du Colombier 		if(fd >= 0)
197dd7cddfSDavid du Colombier 			return fd;
207dd7cddfSDavid du Colombier 	}
217dd7cddfSDavid du Colombier 	return -1;
227dd7cddfSDavid du Colombier }
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier Disk*
257dd7cddfSDavid du Colombier diskinit()
267dd7cddfSDavid du Colombier {
277dd7cddfSDavid du Colombier 	Disk *d;
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier 	d = emalloc(sizeof(Disk));
307dd7cddfSDavid du Colombier 	d->fd = tempdisk();
317dd7cddfSDavid du Colombier 	if(d->fd < 0){
327dd7cddfSDavid du Colombier 		fprint(2, "sam: can't create temp file: %r\n");
337dd7cddfSDavid du Colombier 		exits("diskinit");
347dd7cddfSDavid du Colombier 	}
357dd7cddfSDavid du Colombier 	return d;
367dd7cddfSDavid du Colombier }
377dd7cddfSDavid du Colombier 
387dd7cddfSDavid du Colombier static
397dd7cddfSDavid du Colombier uint
407dd7cddfSDavid du Colombier ntosize(uint n, uint *ip)
417dd7cddfSDavid du Colombier {
427dd7cddfSDavid du Colombier 	uint size;
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier 	if(n > Maxblock)
457dd7cddfSDavid du Colombier 		panic("internal error: ntosize");
467dd7cddfSDavid du Colombier 	size = n;
477dd7cddfSDavid du Colombier 	if(size & (Blockincr-1))
487dd7cddfSDavid du Colombier 		size += Blockincr - (size & (Blockincr-1));
497dd7cddfSDavid du Colombier 	/* last bucket holds blocks of exactly Maxblock */
507dd7cddfSDavid du Colombier 	if(ip)
517dd7cddfSDavid du Colombier 		*ip = size/Blockincr;
527dd7cddfSDavid du Colombier 	return size * sizeof(Rune);
537dd7cddfSDavid du Colombier }
547dd7cddfSDavid du Colombier 
557dd7cddfSDavid du Colombier Block*
567dd7cddfSDavid du Colombier disknewblock(Disk *d, uint n)
577dd7cddfSDavid du Colombier {
587dd7cddfSDavid du Colombier 	uint i, j, size;
597dd7cddfSDavid du Colombier 	Block *b;
607dd7cddfSDavid du Colombier 
617dd7cddfSDavid du Colombier 	size = ntosize(n, &i);
627dd7cddfSDavid du Colombier 	b = d->free[i];
637dd7cddfSDavid du Colombier 	if(b)
647dd7cddfSDavid du Colombier 		d->free[i] = b->next;
657dd7cddfSDavid du Colombier 	else{
667dd7cddfSDavid du Colombier 		/* allocate in chunks to reduce malloc overhead */
677dd7cddfSDavid du Colombier 		if(blist == nil){
687dd7cddfSDavid du Colombier 			blist = emalloc(100*sizeof(Block));
697dd7cddfSDavid du Colombier 			for(j=0; j<100-1; j++)
707dd7cddfSDavid du Colombier 				blist[j].next = &blist[j+1];
717dd7cddfSDavid du Colombier 		}
727dd7cddfSDavid du Colombier 		b = blist;
737dd7cddfSDavid du Colombier 		blist = b->next;
747dd7cddfSDavid du Colombier 		b->addr = d->addr;
757dd7cddfSDavid du Colombier 		d->addr += size;
767dd7cddfSDavid du Colombier 	}
777dd7cddfSDavid du Colombier 	b->n = n;
787dd7cddfSDavid du Colombier 	return b;
797dd7cddfSDavid du Colombier }
807dd7cddfSDavid du Colombier 
817dd7cddfSDavid du Colombier void
827dd7cddfSDavid du Colombier diskrelease(Disk *d, Block *b)
837dd7cddfSDavid du Colombier {
847dd7cddfSDavid du Colombier 	uint i;
857dd7cddfSDavid du Colombier 
867dd7cddfSDavid du Colombier 	ntosize(b->n, &i);
877dd7cddfSDavid du Colombier 	b->next = d->free[i];
887dd7cddfSDavid du Colombier 	d->free[i] = b;
897dd7cddfSDavid du Colombier }
907dd7cddfSDavid du Colombier 
917dd7cddfSDavid du Colombier void
927dd7cddfSDavid du Colombier diskwrite(Disk *d, Block **bp, Rune *r, uint n)
937dd7cddfSDavid du Colombier {
947dd7cddfSDavid du Colombier 	int size, nsize;
957dd7cddfSDavid du Colombier 	Block *b;
967dd7cddfSDavid du Colombier 
977dd7cddfSDavid du Colombier 	b = *bp;
987dd7cddfSDavid du Colombier 	size = ntosize(b->n, nil);
997dd7cddfSDavid du Colombier 	nsize = ntosize(n, nil);
1007dd7cddfSDavid du Colombier 	if(size != nsize){
1017dd7cddfSDavid du Colombier 		diskrelease(d, b);
1027dd7cddfSDavid du Colombier 		b = disknewblock(d, n);
1037dd7cddfSDavid du Colombier 		*bp = b;
1047dd7cddfSDavid du Colombier 	}
1057dd7cddfSDavid du Colombier 	if(seek(d->fd, b->addr, 0) < 0)
1067dd7cddfSDavid du Colombier 		panic("seek error in temp file");
1077dd7cddfSDavid du Colombier 	if(write(d->fd, r, n*sizeof(Rune)) != n*sizeof(Rune))
1087dd7cddfSDavid du Colombier 		panic("write error to temp file");
1097dd7cddfSDavid du Colombier 	b->n = n;
1107dd7cddfSDavid du Colombier }
1117dd7cddfSDavid du Colombier 
1127dd7cddfSDavid du Colombier void
1137dd7cddfSDavid du Colombier diskread(Disk *d, Block *b, Rune *r, uint n)
1147dd7cddfSDavid du Colombier {
1157dd7cddfSDavid du Colombier 	if(n > b->n)
1167dd7cddfSDavid du Colombier 		panic("internal error: diskread");
1177dd7cddfSDavid du Colombier 
1187dd7cddfSDavid du Colombier 	ntosize(b->n, nil);
1197dd7cddfSDavid du Colombier 	if(seek(d->fd, b->addr, 0) < 0)
1207dd7cddfSDavid du Colombier 		panic("seek error in temp file");
1217dd7cddfSDavid du Colombier 	if(read(d->fd, r, n*sizeof(Rune)) != n*sizeof(Rune))
1227dd7cddfSDavid du Colombier 		panic("read error from temp file");
1237dd7cddfSDavid du Colombier }
124