summaryrefslogtreecommitdiff
path: root/appl/lib/diskblocks.b
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/lib/diskblocks.b
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/lib/diskblocks.b')
-rw-r--r--appl/lib/diskblocks.b122
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);
+}