diff options
Diffstat (limited to 'src/cmd/venti/part.c')
-rw-r--r-- | src/cmd/venti/part.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/cmd/venti/part.c b/src/cmd/venti/part.c new file mode 100644 index 00000000..dbf7b860 --- /dev/null +++ b/src/cmd/venti/part.c @@ -0,0 +1,130 @@ +#include "stdinc.h" +#include "dat.h" +#include "fns.h" + +u32int maxblocksize; +int readonly; + +Part* +initpart(char *name, int writable) +{ + Part *part; + Dir *dir; + int how; + + part = MK(Part); + part->name = estrdup(name); + if(!writable && readonly) + how = OREAD; + else + how = ORDWR; + part->fd = open(name, how); + if(part->fd < 0){ + if(how == ORDWR) + part->fd = open(name, OREAD); + if(part->fd < 0){ + freepart(part); + seterr(EOk, "can't open partition='%s': %r", name); + return nil; + } + fprint(2, "warning: %s opened for reading only\n", name); + } + dir = dirfstat(part->fd); + if(dir == nil){ + freepart(part); + seterr(EOk, "can't stat partition='%s': %r", name); + return nil; + } + part->size = dir->length; + part->blocksize = 0; + free(dir); + return part; +} + +void +freepart(Part *part) +{ + if(part == nil) + return; + close(part->fd); + free(part->name); + free(part); +} + +void +partblocksize(Part *part, u32int blocksize) +{ + if(part->blocksize) + sysfatal("resetting partition=%s's block size", part->name); + part->blocksize = blocksize; + if(blocksize > maxblocksize) + maxblocksize = blocksize; +} + +int +writepart(Part *part, u64int addr, u8int *buf, u32int n) +{ + long m, mm, nn; + + qlock(&stats.lock); + stats.diskwrites++; + stats.diskbwrites += n; + qunlock(&stats.lock); + + if(addr > part->size || addr + n > part->size){ + seterr(ECorrupt, "out of bounds write to partition='%s'", part->name); + return -1; + } + print("write %s %lud at %llud\n", part->name, n, addr); + for(nn = 0; nn < n; nn += m){ + mm = n - nn; + if(mm > MaxIo) + mm = MaxIo; + m = pwrite(part->fd, &buf[nn], mm, addr + nn); + if(m != mm){ + if(m < 0){ + seterr(EOk, "can't write partition='%s': %r", part->name); + return -1; + } + logerr(EOk, "truncated write to partition='%s' n=%ld wrote=%ld", part->name, mm, m); + } + } + return 0; +} + +int +readpart(Part *part, u64int addr, u8int *buf, u32int n) +{ + long m, mm, nn; + int i; + + qlock(&stats.lock); + stats.diskreads++; + stats.diskbreads += n; + qunlock(&stats.lock); + + if(addr > part->size || addr + n > part->size){ + seterr(ECorrupt, "out of bounds read from partition='%s': addr=%lld n=%d size=%lld", part->name, addr, n, part->size); + return -1; + } + print("read %s %lud at %llud\n", part->name, n, addr); + for(nn = 0; nn < n; nn += m){ + mm = n - nn; + if(mm > MaxIo) + mm = MaxIo; + m = -1; + for(i=0; i<4; i++) { + m = pread(part->fd, &buf[nn], mm, addr + nn); + if(m == mm) + break; + } + if(m != mm){ + if(m < 0){ + seterr(EOk, "can't read partition='%s': %r", part->name); + return -1; + } + logerr(EOk, "warning: truncated read from partition='%s' n=%ld read=%ld", part->name, mm, m); + } + } + return 0; +} |