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