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