1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <thread.h> 5 #include <mouse.h> 6 #include <keyboard.h> 7 #include <frame.h> 8 #include <auth.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 dir[DIRLEN]; 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(stat(buf, dir) == 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 exits("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->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].next = &blist[j+1]; 82 } 83 b = blist; 84 blist = b->next; 85 b->addr = d->addr; 86 d->addr += size; 87 } 88 b->n = n; 89 return b; 90 } 91 92 void 93 diskrelease(Disk *d, Block *b) 94 { 95 uint i; 96 97 ntosize(b->n, &i); 98 b->next = d->free[i]; 99 d->free[i] = b; 100 } 101 102 void 103 diskwrite(Disk *d, Block **bp, Rune *r, uint n) 104 { 105 int size, nsize; 106 Block *b; 107 108 b = *bp; 109 size = ntosize(b->n, nil); 110 nsize = ntosize(n, nil); 111 if(size != nsize){ 112 diskrelease(d, b); 113 b = disknewblock(d, n); 114 *bp = b; 115 } 116 if(seek(d->fd, b->addr, 0) < 0) 117 error("seek error in temp file"); 118 if(write(d->fd, r, n*sizeof(Rune)) != n*sizeof(Rune)) 119 error("write error to temp file"); 120 b->n = n; 121 } 122 123 void 124 diskread(Disk *d, Block *b, Rune *r, uint n) 125 { 126 if(n > b->n) 127 error("internal error: diskread"); 128 129 ntosize(b->n, nil); 130 if(seek(d->fd, b->addr, 0) < 0) 131 error("seek error in temp file"); 132 if(read(d->fd, r, n*sizeof(Rune)) != n*sizeof(Rune)) 133 error("read error from temp file"); 134 } 135