disk.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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 }