diff options
| author | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2025-10-15 19:46:13 +0200 |
|---|---|---|
| committer | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2025-10-15 19:46:13 +0200 |
| commit | 184526f3bf90e2948b1d09b9da58d66814181f4d (patch) | |
| tree | d39614e3e29fb89594d1dc52ef07805bc754c4c7 /sam/disk.c | |
| parent | fd41e6cc88f98121db5c64a0693e4169962f6c2c (diff) | |
Import sam and samterm sources
Diffstat (limited to 'sam/disk.c')
| -rw-r--r-- | sam/disk.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/sam/disk.c b/sam/disk.c new file mode 100644 index 0000000..e822f48 --- /dev/null +++ b/sam/disk.c @@ -0,0 +1,121 @@ +#include "sam.h" + +static Block *blist; + +static int +tempdisk(void) +{ + char buf[128]; + int i, fd; + + snprint(buf, sizeof buf, "/tmp/X%d.%.4ssam", getpid(), getuser()); + for(i='A'; i<='Z'; i++){ + buf[5] = i; + if(access(buf, AEXIST) == 0) + continue; + fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600); + if(fd >= 0) + return fd; + } + return -1; +} + +Disk* +diskinit() +{ + Disk *d; + + d = emalloc(sizeof(Disk)); + d->fd = tempdisk(); + if(d->fd < 0){ + fprint(2, "sam: can't create temp file: %r\n"); + exits("diskinit"); + } + return d; +} + +static +uint +ntosize(uint n, uint *ip) +{ + uint size; + + if(n > Maxblock) + panic("internal error: ntosize"); + size = n; + if(size & (Blockincr-1)) + size += Blockincr - (size & (Blockincr-1)); + /* last bucket holds blocks of exactly Maxblock */ + if(ip) + *ip = size/Blockincr; + return size * sizeof(Rune); +} + +Block* +disknewblock(Disk *d, uint n) +{ + uint i, j, size; + Block *b; + + size = ntosize(n, &i); + b = d->free[i]; + if(b) + d->free[i] = b->next; + else{ + /* allocate in chunks to reduce malloc overhead */ + if(blist == nil){ + blist = emalloc(100*sizeof(Block)); + for(j=0; j<100-1; j++) + blist[j].next = &blist[j+1]; + } + b = blist; + blist = b->next; + b->addr = d->addr; + if(d->addr+size < d->addr){ + panic("temp file overflow"); + } + d->addr += size; + } + b->n = n; + return b; +} + +void +diskrelease(Disk *d, Block *b) +{ + uint i; + + ntosize(b->n, &i); + b->next = d->free[i]; + d->free[i] = b; +} + +void +diskwrite(Disk *d, Block **bp, Rune *r, uint n) +{ + int size, nsize; + Block *b; + + b = *bp; + size = ntosize(b->n, nil); + nsize = ntosize(n, nil); + if(size != nsize){ + diskrelease(d, b); + b = disknewblock(d, n); + *bp = b; + } + if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune)) + panic("write error to temp file"); + b->n = n; +} + +void +diskread(Disk *d, Block *b, Rune *r, uint n) +{ + if(n > b->n) + panic("internal error: diskread"); + + ntosize(b->n, nil); /* called only for sanity check on Maxblock */ + if(pread(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune)) + panic("read error from temp file"); +} |