9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

disk.c (2058B)


      1 #include "sam.h"
      2 
      3 static	Block	*blist;
      4 
      5 #if 0
      6 static int
      7 tempdisk(void)
      8 {
      9 	char buf[128];
     10 	int i, fd;
     11 
     12 	snprint(buf, sizeof buf, "/tmp/X%d.%.4ssam", getpid(), getuser());
     13 	for(i='A'; i<='Z'; i++){
     14 		buf[5] = i;
     15 		if(access(buf, AEXIST) == 0)
     16 			continue;
     17 		fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
     18 		if(fd >= 0)
     19 			return fd;
     20 	}
     21 	return -1;
     22 }
     23 #else
     24 extern int tempdisk(void);
     25 #endif
     26 
     27 Disk*
     28 diskinit(void)
     29 {
     30 	Disk *d;
     31 
     32 	d = emalloc(sizeof(Disk));
     33 	d->fd = tempdisk();
     34 	if(d->fd < 0){
     35 		fprint(2, "sam: can't create temp file: %r\n");
     36 		exits("diskinit");
     37 	}
     38 	return d;
     39 }
     40 
     41 static
     42 uint
     43 ntosize(uint n, uint *ip)
     44 {
     45 	uint size;
     46 
     47 	if(n > Maxblock)
     48 		panic("internal error: ntosize");
     49 	size = n;
     50 	if(size & (Blockincr-1))
     51 		size += Blockincr - (size & (Blockincr-1));
     52 	/* last bucket holds blocks of exactly Maxblock */
     53 	if(ip)
     54 		*ip = size/Blockincr;
     55 	return size * sizeof(Rune);
     56 }
     57 
     58 Block*
     59 disknewblock(Disk *d, uint n)
     60 {
     61 	uint i, j, size;
     62 	Block *b;
     63 
     64 	size = ntosize(n, &i);
     65 	b = d->free[i];
     66 	if(b)
     67 		d->free[i] = b->u.next;
     68 	else{
     69 		/* allocate in chunks to reduce malloc overhead */
     70 		if(blist == nil){
     71 			blist = emalloc(100*sizeof(Block));
     72 			for(j=0; j<100-1; j++)
     73 				blist[j].u.next = &blist[j+1];
     74 		}
     75 		b = blist;
     76 		blist = b->u.next;
     77 		b->addr = d->addr;
     78 		d->addr += size;
     79 	}
     80 	b->u.n = n;
     81 	return b;
     82 }
     83 
     84 void
     85 diskrelease(Disk *d, Block *b)
     86 {
     87 	uint i;
     88 
     89 	ntosize(b->u.n, &i);
     90 	b->u.next = d->free[i];
     91 	d->free[i] = b;
     92 }
     93 
     94 void
     95 diskwrite(Disk *d, Block **bp, Rune *r, uint n)
     96 {
     97 	int size, nsize;
     98 	Block *b;
     99 
    100 	b = *bp;
    101 	size = ntosize(b->u.n, nil);
    102 	nsize = ntosize(n, nil);
    103 	if(size != nsize){
    104 		diskrelease(d, b);
    105 		b = disknewblock(d, n);
    106 		*bp = b;
    107 	}
    108 	if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
    109 		panic("write error to temp file");
    110 	b->u.n = n;
    111 }
    112 
    113 void
    114 diskread(Disk *d, Block *b, Rune *r, uint n)
    115 {
    116 	if(n > b->u.n)
    117 		panic("internal error: diskread");
    118 
    119 	ntosize(b->u.n, nil);	/* called only for sanity check on Maxblock */
    120 	if(pread(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
    121 		panic("read error from temp file");
    122 }