rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 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* |
rsc | 2b60408 | 2005-05-07 22:42:14 +0000 | [diff] [blame] | 28 | diskinit(void) |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 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) |
rsc | 522b068 | 2003-09-30 19:05:50 +0000 | [diff] [blame] | 67 | d->free[i] = b->u.next; |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 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++) |
rsc | 522b068 | 2003-09-30 19:05:50 +0000 | [diff] [blame] | 73 | blist[j].u.next = &blist[j+1]; |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 74 | } |
| 75 | b = blist; |
rsc | 522b068 | 2003-09-30 19:05:50 +0000 | [diff] [blame] | 76 | blist = b->u.next; |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 77 | b->addr = d->addr; |
| 78 | d->addr += size; |
| 79 | } |
rsc | 522b068 | 2003-09-30 19:05:50 +0000 | [diff] [blame] | 80 | b->u.n = n; |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 81 | return b; |
| 82 | } |
| 83 | |
| 84 | void |
| 85 | diskrelease(Disk *d, Block *b) |
| 86 | { |
| 87 | uint i; |
| 88 | |
rsc | 522b068 | 2003-09-30 19:05:50 +0000 | [diff] [blame] | 89 | ntosize(b->u.n, &i); |
| 90 | b->u.next = d->free[i]; |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 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; |
rsc | 522b068 | 2003-09-30 19:05:50 +0000 | [diff] [blame] | 101 | size = ntosize(b->u.n, nil); |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 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"); |
rsc | 522b068 | 2003-09-30 19:05:50 +0000 | [diff] [blame] | 110 | b->u.n = n; |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 111 | } |
| 112 | |
| 113 | void |
| 114 | diskread(Disk *d, Block *b, Rune *r, uint n) |
| 115 | { |
rsc | 522b068 | 2003-09-30 19:05:50 +0000 | [diff] [blame] | 116 | if(n > b->u.n) |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 117 | panic("internal error: diskread"); |
| 118 | |
rsc | 522b068 | 2003-09-30 19:05:50 +0000 | [diff] [blame] | 119 | ntosize(b->u.n, nil); /* called only for sanity check on Maxblock */ |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 120 | if(pread(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune)) |
| 121 | panic("read error from temp file"); |
| 122 | } |