diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /appl/lib/diskblocks.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/lib/diskblocks.b')
| -rw-r--r-- | appl/lib/diskblocks.b | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/appl/lib/diskblocks.b b/appl/lib/diskblocks.b new file mode 100644 index 00000000..a98505e7 --- /dev/null +++ b/appl/lib/diskblocks.b @@ -0,0 +1,122 @@ +implement Diskblocks; + +# +# adapted from Acme's disk.b +# + +include "sys.m"; + sys: Sys; + +include "diskblocks.m"; + +init() +{ + sys = load Sys Sys->PATH; +} + +tempfile(): ref Sys->FD +{ + user := "inferno"; + fd := sys->open("/dev/user", Sys->OREAD); + if(fd != nil){ + b := array[Sys->NAMEMAX] of byte; + n := sys->read(fd, b, len b); + if(n > 0) + user = string b[0:n]; + } + fd = nil; + buf := sys->sprint("/tmp/X%d.%.4sblks", sys->pctl(0, nil), user); + for(i:='A'; i<='Z'; i++){ + buf[5] = i; + if(sys->stat(buf).t0 == 0) + continue; + fd = sys->create(buf, Sys->ORDWR|Sys->ORCLOSE|Sys->OEXCL, 8r600); + if(fd != nil) + return fd; + } + return nil; +} + +Disk.init(fd: ref Sys->FD, gran: int, maxblock: int): ref Disk +{ + d := ref Disk; + if(gran == 0 || maxblock%gran != 0) + return nil; + d.maxblock = maxblock; + d.gran = gran; + d.free = array[maxblock/gran+1] of list of ref Block; + d.addr = big 0; + d.fd = fd; + d.lock = chan[1] of int; + return d; +} + +ntosize(d: ref Disk, n: int): (int, int) +{ + if (n > d.maxblock) + return (-1, -1); + size := n; + if((size % d.gran) != 0) + size += d.gran - size%d.gran; + # last bucket holds blocks of exactly d.maxblock + return (size, size/d.gran); +} + +Disk.new(d: self ref Disk, n: int): ref Block +{ + (size, i) := ntosize(d, n); + if(i < 0){ + sys->werrstr("illegal Disk allocation"); + return nil; + } + b: ref Block; + d.lock <-= 1; + if(d.free[i] != nil){ + b = hd d.free[i]; + d.free[i] = tl d.free[i]; + }else{ + b = ref Block(d.addr, 0); + d.addr += big size; + } + <-d.lock; + b.n = n; + return b; +} + +Disk.release(d: self ref Disk, b: ref Block) +{ + (nil, i) := ntosize(d, b.n); + d.lock <-= 1; + d.free[i] = b :: d.free[i]; + <-d.lock; +} + +Disk.write(d: self ref Disk, b: ref Block, a: array of byte, n: int): ref Block +{ + if(b != nil){ + (size, nil) := ntosize(d, b.n); + (nsize, nil) := ntosize(d, n); + if(size != nsize){ + d.release(b); + b = d.new(n); + } + }else + b = d.new(n); + if(b == nil) + return nil; + if(sys->pwrite(d.fd, a, n, b.addr) != n){ + sys->werrstr(sys->sprint("Disk write error: %r")); + return nil; + } + b.n = n; + return b; +} + +Disk.read(d: self ref Disk, b: ref Block, a: array of byte, n: int): int +{ + if(b == nil || n > b.n){ + sys->werrstr("read request bigger than block"); + return -1; + } + return sys->pread(d.fd, a, n, b.addr); +} |
