#include "stdinc.h" #include "dat.h" #include "fns.h" #define trace 1 u32int maxblocksize; int readonly; Part* initpart(char *name, int writable) { Part *part; Dir *dir; int how; part = MKZ(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; } if(trace) 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; } if(trace) 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; }